Skip to content
This repository has been archived by the owner on Jun 5, 2019. It is now read-only.

Code In NETMF Operating System Does Not Transfer to C# DLL's #541

Open
patrickmealey opened this issue Mar 18, 2017 · 3 comments
Open

Code In NETMF Operating System Does Not Transfer to C# DLL's #541

patrickmealey opened this issue Mar 18, 2017 · 3 comments

Comments

@patrickmealey
Copy link

Having a problem in which I have enabled code for a micro SD card on a port of NETMF to the STM32 F7 Nucleo. This port was originally done by CW2 and did not include micro SD support.

The code is correctly compiled and loaded into the NETMF interpreter and, via GDB, onto the Nucleo board. Can set breakpoints and single step.

The corresponding DLL, however, does not have a table entry for the routine. Or rather, it has an empty (RVA=0xFFFF) entry.

So my question is, which tool parses the interpreter code and generates the DLL's? I have examined the build log (msbuild.log) and note that "metadataprocessor.exe" is called around the time that the DLL's are generated, but he precise methodology escapes me.

And a related question is, how does one create a new routine, callable from C#, in the C++ domain? The name must be correctly mangled. I noticed for Microsoft.Spot.IO.NativeIO there is reference to a tool which generated the file "spot_io_native_Microsoft_SPOT_IO_NativeIO.h". Which tool is that and how do I use it?

Thanks in advance for any help.

@techcap
Copy link
Contributor

techcap commented Mar 22, 2017

@smaillet-ms
Copy link
Member

It's not clear what DLLs you are refereeing to. As NETMF on the device at run time, doesn't have any DLLs. The Standard C# compiler generates a DLL, which is then processed by MetadataProcessor into a .pe file which is the NETMF specific condensed IL code burned into FLASH on the device. The interpreter will read that IL representation when executing the code. For interop, the article @techcap mentions is a great starting point, there's more low level implementation details of the PE files available from the "Book of the Runtime" topic I wrote up.

@patrickmealey
Copy link
Author

patrickmealey commented Mar 22, 2017

Thank you so much for responding. I was not having much success in discovering the mechanisms used in bridging the C# to C++ divide. I will assiduously study this.

My apologies for not being more specific. I will describe the problem in more depth while attempting to be brief.

I added several projects to support the micro SD card:
Stream.featureproj
FileSystem.featureproj
DataStorage.featureproj
SPOT_IO.lib
Stream.lib
FS_FAT.lib
fs_pal.lib
FileSystem_Config_PAL
SD_BL.lib

and then wrote a file:

"FileSystem_Config_STM32F746NUCLEO.cpp"

which hooks to the SPI driver to talk to the micro SD device. I based this on the Netduino code for their micro SD card.

I then removed all of the references to the stub files for these projects from the build scripts.

The problem that I am having is in debugging the system.

The last call in the C# code before the interop call to the C++ code is:

"uint attributes = NativeIO.GetAttributes(_fileName);" in ......\Framework\Core\System\IO\FileStream.cs.

As nearly as I can determine this is supposed to call the routine:

"HRESULT Library_spot_io_native_Microsoft_SPOT_IO_NativeIO::GetAttributes___STATIC__U4__STRING(CLR_RT_StackFrame& stack)"

in the file spot_io_native_Microsoft_SPOT_IO_NativeIO.cpp.

The GDB debugger does break for other calls so I know the debugger is working, but I never see this routine executed. Instead what I get from the C# code is an immediate return with the "System.NotSupportedException".

I put a breakpoint on the C# side on the NativeIO.GetAttributes call. When it hit that breakpoint, I switched to the C++ code

I put the breakpoint on :

HRESULT CLR_RT_Thread::Execute_IL( CLR_RT_StackFrame* stack );

in Interpreter.cpp. That breakpoint does occur and I stepped through the interpreter code.

After stepping through the Execute_IL routing it appears to me that the interpreter is attempting to call a routine at an invalid address. The interpreter fails in routine: CLR_RT_StackFrame::PushInline(...) in CLR_RT_StackFrame.cpp.

The particular value which causes the failure is md-RVA. I found the dump files for the NETMF DLL's and looked at the Microsoft .SPOT.IO.dump for the routine: Microsoft.SPOT.IO.NativeIO::GetAttributes [METHOD U4( STRING )]. The RVA (Relative Virtual Address) is set to 0xFFFF, which means that there is no entry in the DLL for this call.

So, to reiterate, the C++ code for the call (GetAttributes) exists, but the DLL (Microsoft.SPOT.IO.dll) does not instantiate an entry for this code. So my C++ code is never called.

This seems to me to be a failure in my understanding of the build system. My expectation was that the DLL would be automagically generated with the correct pointers to the operating system code. Clearly, that is not happening.

I am perfectly willing to post my code somewhere. Hope this is enough detail to explain what I discovered. I will continue working on this using the information you folks have thoughtfully provided.

Thanks again!

Patrick

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants