Comments (23)
What hardware are you running this on? And is there a specific reason why you run your app in a container? This adds additional complexity.
from iot.
This is running on a custom linux arm iot platform using the azure iot edge runtime. We are using the container runtime from iot edge to deploy our application to the device.
from iot.
The callback is known to work on other platforms, so there must be something special about yours, maybe the libgpiod driver is not fully compatible. Have you tried the sysfs driver?
from iot.
When using the SysFs driver the following exception was thrown when pressing the button connected to the pin:
Unhandled exception. System.IO.IOException: Error while trying to seek in value file.
at System.Device.Gpio.Drivers.SysFsDriver.WasEventDetected(Int32 pollFileDescriptor, Int32 valueFileDescriptor, Int32& pinNumber, CancellationToken cancellationToken)
at System.Device.Gpio.Drivers.SysFsDriver.DetectEvents()
at System.Threading.Thread.StartHelper.Callback(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Thread.StartCallback()
from iot.
[Triage] are you forwarding pin related directories to the docker container? what's the exact command line you're using to run your container? (or at least relevant pieces to GPIO) If you can please also share dockerfile
from iot.
Here are some basic instructions how to run in the container: https://github.com/dotnet/iot/tree/main/samples/led-blink (last command line is for sysfs)
from iot.
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.
from iot.
are you forwarding pin related directories to the docker container?
Yes, we run the container privileged and we forwarded the directory to the container.
what's the exact command line you're using [...] please also share dockerfile
# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:7.0.1-alpine3.17
ARG PROJ_NAME
ARG PORT
VOLUME /hostpipe
VOLUME /scripts
VOLUME /libsFromHost
COPY --from=build /testresults /testresults
WORKDIR /app
COPY --from=build /app .
COPY --from=build /app/CBinaries/*.so /app
EXPOSE $PORT
EXPOSE 80
# Copy repository configuration (optional)
COPY alpinehelper/etc/apk/repositories /etc/apk/repositories
# Copy our local repository
COPY alpinehelper/usr/local/repo /usr/local/repo
# Copy keys which we generated previously
COPY alpinehelper/etc/apk/keys /etc/apk/keys
RUN apk --no-cache add libmodbus libmodbus-dev
RUN echo "chmod a+r /dev/ttySTM3" > ./entrypoint.sh
RUN apk --no-cache add libgpiod-dev gpsd
RUN echo "gpsd /dev/ttySTM3 -F /var/run/gpsd.sock" >> ./entrypoint.sh
RUN echo "./${PROJ_NAME}" >> ./entrypoint.sh
RUN cat ./entrypoint.sh
RUN chmod 777 ./entrypoint.sh
ENTRYPOINT ./entrypoint.sh
from iot.
Thanks for the Dockerfile. We would also need the docker run command to see how are you volume-mounting the necessary files for sysfs driver to work.
from iot.
We are using the azure iot edge runtime to deploy and start our containers. To do that we don't provide a command but a manifest where we define modules. We tried three different things, I will list the attempts below:
Attempt 1: only running privileged
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485",
"/sys:/sys"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/sys",
"Target": "/sys",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
Attempt 2: Binding /sys
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485",
"/sys:/sys"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/sys",
"Target": "/sys",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
Attempt 3: Binding gpiochip
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485",
"/dev/gpiochip2:/dev/gpiochip2",
"/dev/mem:/dev/mem"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/gpiochip2",
"PathInContainer": "/dev/gpiochip2",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/mem",
"PathInContainer": "/dev/mem",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
None of these attempts worked out.
from iot.
Thanks @m4schini
Can you try priviledged with /dev to /dev and /sys to /sys binding. That should definitely work.
Then, you can restrict, depending on the GPIO you're using. They will bind differently if sysfs or libgpio, etc.
Check out the source code here for the driver you need (assuming you have the proper lib installed into the container): https://github.com/dotnet/iot/tree/main/src/System.Device.Gpio/System/Device/Gpio
from iot.
We tried it as you described and the behavior for both Sysfs and libgpio is unchanged.
For reference the manifests we used:
Deployment manifest (/sys as device)
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485",
"/dev:/dev",
"/sys:/sys"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev",
"PathInContainer": "/dev",
"CgroupPermissions": "rwm"
},
{
"Source": "/sys",
"Target": "/sys",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/execpipe",
"Target": "/hostpipe",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
Deployment manifest (/sys not as device)
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485",
"/dev:/dev",
"/sys:/sys"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev",
"PathInContainer": "/dev",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/execpipe",
"Target": "/hostpipe",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
In addition to that we also tried to do the same with a slightly different manifest. This time instead of "Binds" we used "Mounts" with bind type:
Deployment manifest
"module": {
"startupOrder": 1,
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "",
"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "5m",
"max-file": "1"
}
},
"Privileged": true,
"Binds": [
"/dev/ttyWifi:/dev/ttyWifi",
"/dev/ttyRS485:/dev/ttyRS485"
],
"IpcMode": "shareable",
"CapAdd": [
"NET_ADMIN"
],
"Devices": [
{
"PathOnHost": "/dev/ttyWifi",
"PathInContainer": "/dev/ttyWifi",
"CgroupPermissions": "rwm"
},
{
"PathOnHost": "/dev/ttyRS485",
"PathInContainer": "/dev/ttyRS485",
"CgroupPermissions": "rwm"
}
],
"Mounts": [
{
"Source": "/lib",
"Target": "/libsFromHost",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/execpipe",
"Target": "/hostpipe",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/mnt/pData/scripts",
"Target": "/scripts",
"Type": "bind",
"ReadOnly": false
},
{
"PathOnHost": "/dev",
"PathInContainer": "/dev",
"Type": "bind",
"ReadOnly": false
},
{
"Source": "/sys",
"Target": "/sys",
"Type": "bind",
"ReadOnly": false
}
],
"PortBindings": {
"4444/tcp": [
{
"HostPort": "4444"
}
],
"80/tcp": [
{
"HostPort": "80"
}
]
}
}
}
},
And got the following error in the iot edge agent (which is starting the container on the device)
System.AggregateException: One or more errors occurred. (Error calling Create module module: runtime operation error: create module "module")
---> Microsoft.Azure.Devices.Edge.Agent.Edgelet.EdgeletCommunicationException- Message:Error calling Create module module: runtime operation error: create module "module", StatusCode:400, at: at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Version_2022_08_03.ModuleManagementHttpClient.HandleException(Exception exception, String operation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/version_2022_08_03/ModuleManagementHttpClient.cs:line 232
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Versioning.ModuleManagementHttpClientVersioned.Execute[T](Func`1 func, String operation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/versioning/ModuleManagementHttpClientVersioned.cs:line 171
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Version_2022_08_03.ModuleManagementHttpClient.CreateModuleAsync(ModuleSpec moduleSpec) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/version_2022_08_03/ModuleManagementHttpClient.cs:line 102
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.ModuleManagementHttpClient.<>c__DisplayClass26_0.<<Throttle>b__0>d.MoveNext() in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleManagementHttpClient.cs:line 145
--- End of stack trace from previous location ---
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.ModuleManagementHttpClient.Throttle[T](Func`1 identityOperation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleManagementHttpClient.cs:line 164
at Microsoft.Azure.Devices.Edge.Agent.Core.Commands.GroupCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/commands/GroupCommand.cs:line 35
at Microsoft.Azure.Devices.Edge.Agent.Core.LoggingCommandFactory.LoggingCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/LoggingCommandFactory.cs:line 69
at Microsoft.Azure.Devices.Edge.Agent.Core.Commands.GroupCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/commands/GroupCommand.cs:line 35
at Microsoft.Azure.Devices.Edge.Agent.Core.LoggingCommandFactory.LoggingCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/LoggingCommandFactory.cs:line 69
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.ExecuteAsync(Int64 deploymentId, Plan plan, CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/planrunner/OrdererdRetryPlanRunner.cs:line 91
--- End of inner exception stack trace ---
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.<>c.<ExecuteAsync>b__7_0(List`1 f) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/planrunner/OrdererdRetryPlanRunner.cs:line 129
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.ExecuteAsync(Int64 deploymentId, Plan plan, CancellationToken token)
at Microsoft.Azure.Devices.Edge.Agent.Core.Agent.ReconcileAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs:line 208
<4> 2023-09-21 08:58:23.738 +00:00 [WRN] - Reconcile failed because of the an exception
System.AggregateException: One or more errors occurred. (Error calling Create module module: runtime operation error: create module "module")
---> Microsoft.Azure.Devices.Edge.Agent.Edgelet.EdgeletCommunicationException- Message:Error calling Create module module: runtime operation error: create module "module", StatusCode:400, at: at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Version_2022_08_03.ModuleManagementHttpClient.HandleException(Exception exception, String operation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/version_2022_08_03/ModuleManagementHttpClient.cs:line 232
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Versioning.ModuleManagementHttpClientVersioned.Execute[T](Func`1 func, String operation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/versioning/ModuleManagementHttpClientVersioned.cs:line 171
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.Version_2022_08_03.ModuleManagementHttpClient.CreateModuleAsync(ModuleSpec moduleSpec) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/version_2022_08_03/ModuleManagementHttpClient.cs:line 102
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.ModuleManagementHttpClient.<>c__DisplayClass26_0.<<Throttle>b__0>d.MoveNext() in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleManagementHttpClient.cs:line 145
--- End of stack trace from previous location ---
at Microsoft.Azure.Devices.Edge.Agent.Edgelet.ModuleManagementHttpClient.Throttle[T](Func`1 identityOperation) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleManagementHttpClient.cs:line 164
at Microsoft.Azure.Devices.Edge.Agent.Core.Commands.GroupCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/commands/GroupCommand.cs:line 35
at Microsoft.Azure.Devices.Edge.Agent.Core.LoggingCommandFactory.LoggingCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/LoggingCommandFactory.cs:line 69
at Microsoft.Azure.Devices.Edge.Agent.Core.Commands.GroupCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/commands/GroupCommand.cs:line 35
at Microsoft.Azure.Devices.Edge.Agent.Core.LoggingCommandFactory.LoggingCommand.ExecuteAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/LoggingCommandFactory.cs:line 69
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.ExecuteAsync(Int64 deploymentId, Plan plan, CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/planrunner/OrdererdRetryPlanRunner.cs:line 91
--- End of inner exception stack trace ---
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.<>c.<ExecuteAsync>b__7_0(List`1 f) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/planrunner/OrdererdRetryPlanRunner.cs:line 129
at Microsoft.Azure.Devices.Edge.Agent.Core.PlanRunner.OrderedRetryPlanRunner.ExecuteAsync(Int64 deploymentId, Plan plan, CancellationToken token)
at Microsoft.Azure.Devices.Edge.Agent.Core.Agent.ReconcileAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs:line 208
at Microsoft.Azure.Devices.Edge.Agent.Core.Agent.ReconcileAsync(CancellationToken token) in /mnt/vss/_work/1/s/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Agent.cs:line 208
Check out the source code here for the driver you need
We use, depending on what we are testing, either SysFsDriver.cs or LibGpiodDriver.cs.
(assuming you have the proper lib installed into the container)
We confirmed that both work inside the container with the usual command line utilities.
from iot.
[Triage] - Sorry @m4schini I know we suggested above to try sysfs but I somehow missed the part you saying that you were running on iot edge. We believe that this is a limitation of azure iot edge where you can't really volume mount the paths you need in order for sysfs driver to work. All that said, in general we usually prefer libgpiod driver as that is usually much more accurate, so I think it's worth going back to that versio instead and figure out what's wrong there. Is it just eventing that is not working for you? What I mean by this is, if you write to a pin which is connected to another pin, do you see the values changing?
from iot.
Yes we also expect the problem to be Eventing related because of the behavior we observed (inside the container):
- We can write and read pin values in C# code with the libgpiod driver
- We can write and read pin values with the gpiolib command line tools
- We can also observe pin value changes via
gpiomon
:
gpiomon 2 12
event: RISING EDGE offset: 12 timestamp: [ 54.261767639]
event: FALLING EDGE offset: 12 timestamp: [ 54.425665514]
from iot.
I'm going on Vacation, my collegue (@ignaciocaramba) will be taking over this issue from our side.
from iot.
As a side note:
If we comment out this section in the SysFsDriver "it works" (we get events on change):
private unsafe bool WasEventDetected(int pollFileDescriptor, int valueFileDescriptor, out int pinNumber, CancellationToken cancellationToken)
{
char buf;
IntPtr bufPtr = new IntPtr(&buf);
pinNumber = -1;
while (!cancellationToken.IsCancellationRequested)
{
// Wait until something happens
int waitResult = CustomInterop.CustomInterop.epoll_wait(pollFileDescriptor, out epoll_event events, 1, PollingTimeout);
if (waitResult == -1)
{
var errorCode = Marshal.GetLastWin32Error();
if (errorCode == ERROR_CODE_EINTR)
{
// ignore Interrupted system call error and retry
continue;
}
throw new IOException($"Error while waiting for pin interrupts. (ErrorCode={errorCode})");
}
if (waitResult > 0)
{
pinNumber = events.data.pinNumber;
/* WE COMMENTED OUT THIS SECTION
// This entire section is probably not necessary, but this seems to be hard to validate.
// See https://github.com/dotnet/iot/pull/914#discussion_r389924106 and issue #1024.
if (valueFileDescriptor == -1)
{
// valueFileDescriptor will be -1 when using the callback eventing. For WaitForEvent, the value will be set.
valueFileDescriptor = _devicePins[pinNumber].FileDescriptor;
}
int lseekResult = CustomInterop.CustomInterop.lseek(valueFileDescriptor, 0, SeekFlags.SEEK_SET);
if (lseekResult == -1)
{
throw new IOException("Error while trying to seek in value file.");
}
int readResult = CustomInterop.CustomInterop.read(valueFileDescriptor, bufPtr, 1);
if (readResult != 1)
{
throw new IOException("Error while trying to read value file.");
}
*/
return true;
}
}
return false;
}
from iot.
That's interesting, in particular due to the comment there. Can you check what the value of valueFileDescriptor
is before and after the first "if" in that section?
from iot.
@pgrawehr
before: -1
after: 329
from iot.
@pgrawehr any updates?
from iot.
@ignaciocaramba Sorry, I didn't have time to look into this. Since it appears to be working if you comment out that block of code (whose existing comment already says that it's questionable), we could verify whether removing that would cause the other boards to break. Can you submit a PR with that piece of code commented out? That would trigger the CI run and we would see whether it directly causes any issues. CI is running a bunch of GPIO tests on actual hardware.
from iot.
@pgrawehr Pr created and All tests have passed
from iot.
The pr fixes the issue with the SysfsDriver, but our initial problem is not fixed: if instead of using Sysfs we use LibGpiod when registering a Callback via RegisterCallbackForPinValueChangedEvent and changing the value of the gpio pin, the callback is not being called.
Also, is there a problem to use SysfsDriver instead of LibgpiodDriver for listening to button events?
from iot.
@ignaciocaramba You seem to have some special hardware there, and it was kind of a coincidence that it could be so easily fixed for Sysfs. When it doesn't work with libgpiod the problem is probably in the library or the hardware and there's likely nothing we can do on our side.
SysFs is generally much slower than libgpiod. If you use this only for buttons, the impact will be negligible. If you need to handle events in the Kilohertz range, then sysfs might not be fast enough and you will loose events.
from iot.
Related Issues (20)
- Iot.Device.Media VideoDevice Capture creates corrupt images with Raspberry PI Camera module 3 HOT 17
- I2S Missing HOT 3
- Does the library support TRF7970A? HOT 3
- FT232H Cannot register for pin value change events HOT 2
- Update Raspberry Pi samples suggesting modifying config.txt settings HOT 5
- Unable to set pin mode on pi5 HOT 4
- Breaking change: Y2038 support for .NET Arm32 HOT 1
- arix.local HOT 1
- Misleading XML summary for ButtonBase.IsPressed HOT 1
- TM16xx is very unstable - shows strange characters most of the time HOT 7
- GPIO input gives segmentation fault on BeagleBone Black in v3.1.0 HOT 20
- Implement Raspberry5Driver and board HOT 1
- Add support for SPI devices that use separate GPIO outputs for Data/Command and Reset HOT 4
- If using gpio on an arm Linux system. How do I make things displayed on the interface? HOT 2
- Unable to get consistent manual exposures HOT 6
- PinNumberingScheme.Board is broken HOT 2
- SPI communication on RPI5 is possibly broken
- ButtonBase.IsPressed not properly initialized HOT 1
- Investigate protocol: matter HOT 1
- Cargo causes GpioController to hang on Raspberry Pi 5 Bookworm HOT 31
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from iot.