Recent

Author Topic: Extend WiringPi wrapper "hwiringpi"  (Read 4219 times)

Mountaineer

  • New Member
  • *
  • Posts: 11
Extend WiringPi wrapper "hwiringpi"
« on: May 08, 2021, 11:50:47 am »
Hi folks!
I tried to extend WiringPi wrapper "hwiringpi" from:
https://forum.lazarus.freepascal.org/index.php/topic,17404.msg95833.html#msg95833

I tried to add the function "wiringPiISR"...
(wiringPi reference: int wiringPiISR (int pin, int edgeType,  void (*function)(void)) ;)
But I don't know how to code the last parameter "void (*function)(void))" in the Pascal wrapper.

Please help!

Thaddy

  • Hero Member
  • *****
  • Posts: 10783
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #1 on: May 08, 2021, 11:54:30 am »
It is a pointer to a - pascal speak - procedure.
You can either declare it as var or access it with @

It is quite easy, but today I have little time.
If this clue does not help, plz report back. Sunday I have more time.
(But I think by then it will be answered)

Note the var option is usually better, in this case!
« Last Edit: May 08, 2021, 12:06:55 pm by Thaddy »

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #2 on: May 08, 2021, 05:15:18 pm »
Hello Thaddy,
thanks for your reply!

I want to try the following:

Function wiringPiISR (pin:longint; edgeType:longint;  var callback):longint;cdecl;external;

Is this correct?

ccrause

  • Sr. Member
  • ****
  • Posts: 389
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #3 on: May 08, 2021, 07:04:31 pm »
Function wiringPiISR (pin:longint; edgeType:longint;  var callback):longint;cdecl;external;

Is this correct?
That may not work, but test it to be sure.  I prefer to use a typed parameter, that way the compiler can help ensure that you only pass a procedure with the correct signature:
Code: Pascal  [Select][+][-]
  1. type
  2.   TIsrProc = procedure(); cdecl;  // cdecl probably not required here
  3.  
  4. function wiringPiISR(pin: longint; edgeType: longint; var callback: TIsrProc); longint; cdecl; external;
  5.  
  6. procedure myISR; cdecl; // not necessary since no parameters are passed.
  7. begin
  8. end;
  9.  
  10. begin
  11.   wiringPiISR(1, 1, @myISR);  
  12. end.

Edit: added comment.
« Last Edit: May 08, 2021, 08:27:51 pm by ccrause »

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #4 on: May 08, 2021, 08:03:53 pm »
Hello ccrause,

thank you very much for the code example!
I'm a newbie therfore I need such detailed information!

cheers,

Mountaineer

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #5 on: May 09, 2021, 09:49:47 am »
Hello ccrause,

it's me again!  :-[

Got an error (see below):

Projekt kompilieren, Ziel: project1: Exit code 1, Fehler: 1, Hinweise: 1
unit1.pas(61,27) Error: Call by var for arg no. 3 has to match exactly: Got "<address of procedure;StdCall>" expected "<procedure variable type of procedure;CDecl>"
hwiringpi_DHA.pas(73,10) Hint: Found declaration: wiringPiISR(LongInt;LongInt;var TIsrProc):LongInt; CDecl;


Please help!

ccrause

  • Sr. Member
  • ****
  • Posts: 389
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #6 on: May 09, 2021, 10:34:20 am »
Hello ccrause,

it's me again!  :-[

Got an error (see below):

Projekt kompilieren, Ziel: project1: Exit code 1, Fehler: 1, Hinweise: 1
unit1.pas(61,27) Error: Call by var for arg no. 3 has to match exactly: Got "<address of procedure;StdCall>" expected "<procedure variable type of procedure;CDecl>"
hwiringpi_DHA.pas(73,10) Hint: Found declaration: wiringPiISR(LongInt;LongInt;var TIsrProc):LongInt; CDecl;


Please help!

My apologies, I typed the one version that doesn't work (and also didn't test it, hence all the typo's in the code) :-[ Below a couple of different versions that does compile (at least pass syntax check, I am not linking the executable).  The example also tries to call the wiringPiISR functions with an incorrect procedure signature as a parameter, which the compiler should reject with an error.  This is why I prefer to use typed parameters.

Note that the exact method of passing a procedure as a parameter differ slightly depending on the compiler mode.  In mode ObjFPC or Delphi the following should work:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. type
  4.   TISRProc = procedure(); cdecl;
  5.  
  6. function wiringPiISR_1(pin: longint; edgeType: longint; const callback: TISRProc): longint; cdecl; external;
  7. function wiringPiISR_2(pin: longint; edgeType: longint; callback: TISRProc): longint; cdecl; external;
  8. function wiringPiISR_3(pin: longint; edgeType: longint; constref callback: TISRProc): longint; cdecl; external;
  9.  
  10. procedure correctProc; cdecl;
  11. begin
  12. end;
  13.  
  14. procedure wrongProc(i: integer); cdecl;
  15. begin
  16. end;
  17.  
  18. begin
  19.   // These calls compile
  20.   wiringPiISR_1(1, 1, @correctProc);
  21.   wiringPiISR_2(1, 1, @correctProc);
  22.   wiringPiISR_3(1, 1, @correctProc);
  23.  
  24.   // These calls do not compile
  25.   wiringPiISR_1(1, 1, @wrongProc);
  26.   wiringPiISR_2(1, 1, @wrongProc);
  27.   wiringPiISR_3(1, 1, @wrongProc);
  28. end.

The version below only works in mode Delphi:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. type
  4.   TISRProc = procedure(); cdecl;
  5.  
  6. function wiringPiISR_1(pin: longint; edgeType: longint; const callback: TISRProc): longint; cdecl; external;
  7. function wiringPiISR_2(pin: longint; edgeType: longint; callback: TISRProc): longint; cdecl; external;
  8. function wiringPiISR_3(pin: longint; edgeType: longint; constref callback: TISRProc): longint; cdecl; external;
  9.  
  10. procedure correctProc; cdecl; // not necessary since no parameters are passed.
  11. begin
  12. end;
  13.  
  14. procedure wrongProc(i: integer); cdecl;
  15. begin
  16. end;
  17.  
  18. begin
  19.   // These calls compile
  20.   wiringPiISR_1(1, 1, correctProc);
  21.   wiringPiISR_2(1, 1, correctProc);
  22.   wiringPiISR_3(1, 1, correctProc);
  23.  
  24.   // These calls do not compile
  25.   wiringPiISR_1(1, 1, wrongProc);
  26.   wiringPiISR_2(1, 1, wrongProc);
  27.   wiringPiISR_3(1, 1, wrongProc);
  28. end.

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #7 on: May 09, 2021, 06:15:03 pm »
Hello ccrause,
thank you for your reply!
I tried to use your new code but got this error (same at all of the 3 versions): %)

Projekt kompilieren, Ziel: project1: Exit code 1, Fehler: 1, Warnungen: 2
project1.lpr(23,0) Warning: "crtbegin.o" not found, this will probably cause a linking failure
project1.lpr(23,0) Warning: "crtend.o" not found, this will probably cause a linking failure
project1.lpr(23,0) Error: Error while linking


Please help!

ccrause

  • Sr. Member
  • ****
  • Posts: 389
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #8 on: May 09, 2021, 09:23:19 pm »
project1.lpr(23,0) Error: Error while linking[/i]
Progress of some sorts. Seems like the linker either cannot locate the library, or the new function you are trying to wrap.

Where is the library located that contains the new wiringPiISR function, and how are you specifying the library name and location to the compiler? 

Can you compile and run the original code that you are trying to modify?

Did you notice there is already an implementation that contains the wiringPiISR definition: https://github.com/laz2wiringpi/laz2wiringpi/blob/6680c13011d2b8feda47253824e1ff88edf14523/h2wiringpi.pas#L362

At least there (around line 40) you can see the linklib statements required to link to the C library.

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #9 on: May 12, 2021, 03:37:00 pm »
Hello ccrause,
thank you for supporting me!
After trying this and that I got my program compiling with the wrapper "h2wiringPi"!
No compiling errors (without calling a function or procedure of wiringpi)...
...BUT:
As soon as I uncomment the call "wiringPiISR(1, 1, @myISR);" in my test-program/unit it stops without showing the form (in my experience this is usually due to an error).
But compiling was ok.

Do you have any idea what's going wrong?

Enclosed you will find my test-program/unit (unit1) and the wrapper (h2wiringpi)

VisualLab

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #10 on: May 12, 2021, 05:48:32 pm »
Maybe this article will be helpful when converting C code to Object Pascal code:

http://rvelthuis.de/articles/articles-convert.html

When it comes to using pointers in Object Pascal, this article can be useful:

http://rvelthuis.de/articles/articles-pointers.html

I used these guides myself at one time. These guides are about Delphi, but most of the topics covered will be in line with FPC / Lazarus.

P.S. If my eyes deceive me, at:

http://wiringpi.com/the-gpio-utility/

the author of this library (otherwise useful) states that it uses the system interface: sys / class / gpio. Another interface has appeared in Linux for some time (probably since 2016): dev / gpio. The first one is to be completely removed as obsolete in some time, because it has various disabilities (some problems with interrupts). These pages (examples) describe the difference between them:

https://www.beyondlogic.org/an-introduction-to-chardev-gpio-and-libgpiod-on-the-raspberry-pi/
https://microhobby.com.br/blog/2020/02/02/new-linux-kernel-5-5-new-interfaces-in-gpiolib/
https://www.cnx-software.com/2017/11/03/learn-more-about-linuxs-new-gpio-user-space-subsystem-libgpiod/
https://embeddedbits.org/new-linux-kernel-gpio-user-space-interface/

I'm also trying my hand at creating a simple library to support GPIO, PWM and serial buses (I2C, SPI). I want to use it not only in RPi but also with Up Squared board. The idea is that this library should be object oriented, simple and using system interfaces (e.g. the mentioned dev / gpio). Then you can use this library in various boards equipped with a connector similar to the one in RPi. But there is a long way to the end of my work (if it ever happens). Mainly because the Linux source files code is, to put it mildly, a jungle (and to put it bluntly, there is one big cesspool, among other things because of these ubiquitous preprocessor macros).

ccrause

  • Sr. Member
  • ****
  • Posts: 389
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #11 on: May 12, 2021, 07:01:10 pm »
As soon as I uncomment the call "wiringPiISR(1, 1, @myISR);" in my test-program/unit it stops without showing the form (in my experience this is usually due to an error).
But compiling was ok.

Do you have any idea what's going wrong?
There isn't a call to one of the setup functions.  There may be more subtle configuration problems if you just call functions at random. Permissions to access the hardware may have to be given to the user running the software.  I don't have a Pi configured for testing so cannot help with actual testing on hardware.

Perhaps you should look for a working example in another language and translate that code, for example https://github.com/WiringPi/WiringPi/blob/master/examples/isr.c.

avra

  • Hero Member
  • *****
  • Posts: 2128
    • Additional info
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #12 on: May 13, 2021, 08:16:14 am »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Mountaineer

  • New Member
  • *
  • Posts: 11
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #13 on: May 13, 2021, 04:49:03 pm »
Hello ccrause!
After running wiringpisetup the wiringPiISR-routine is working correctly...
At least no error from compiler and form is displayed correctly.
Thank you very much for helping!  :)

Hello avra!
Thanks for your reply!


One problem solved, the next one is on the way... %)
In order to wait for an interrupt usually endless loops are used.
But this blocks the GUI.
Using other programming languages I solved this with multithreading. (but in Pascal I do not know how to implement multithreading)
Is there a better way to wait for an interrupt while GUI is nonblocking in Pascal/Lazarus?
Could you please give me a hint where to find such (solved) problems inside this forum?
Should I start a new thread for this problem?

ccrause

  • Sr. Member
  • ****
  • Posts: 389
Re: Extend WiringPi wrapper "hwiringpi"
« Reply #14 on: May 13, 2021, 06:38:12 pm »
One problem solved, the next one is on the way... %)
In order to wait for an interrupt usually endless loops are used.
But this blocks the GUI.
Using other programming languages I solved this with multithreading. (but in Pascal I do not know how to implement multithreading)
Is there a better way to wait for an interrupt while GUI is nonblocking in Pascal/Lazarus?
Could you please give me a hint where to find such (solved) problems inside this forum?
Should I start a new thread for this problem?
Perhaps you need to give an example here, in my limited understanding wiringPi relies on the OS kernel to call the interrupt handler. So no waiting is required?  Perhaps you need to explain a bit more what your requirements are.

My view is an interrupt handler should execute time critical code only (like stop motor when limit switch is activated), other actions (alert human, write to log etc) that can wait a couple of ms can easily be handled with a custom message sent to the main form of a GUI application. A very simple example (untested code):
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, LCLIntf, LMessages,
  9.   StdCtrls;
  10.  
  11. const
  12.   WM_ISR = LM_User + 1;
  13.  
  14. type
  15.   { TForm1 }
  16.   TForm1 = class(TForm)
  17.     procedure FormShow(Sender: TObject);
  18.   private
  19.     procedure HandleISRMessage(var msg: TLMessage); message WM_ISR;
  20.   public
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. uses
  29.   hwiringpi;
  30.  
  31. procedure pinTriggered; cdecl;
  32. begin
  33.   // Switch a pin low to stop
  34.   digitalWrite(0, 0);
  35.   // Post a message to GUI form, could even provide more information in last two parameters
  36.   PostMessage(Form1.Handle, WM_ISR, 0, 0);
  37. end;
  38.  
  39. {$R *.lfm}
  40.  
  41. { TForm1 }
  42.  
  43. procedure TForm1.FormShow(Sender: TObject);
  44. begin
  45.   wiringPiSetup;
  46.   // Register pin ISR
  47.   wiringPiISR_1(1, 1, @pinTriggered);
  48.   // Switch a pin high to start
  49.   digitalWrite(0, 1);
  50. end;
  51.  
  52. procedure TForm1.HandleISRMessage(var msg: TLMessage);
  53. begin
  54.   Caption := 'ISR triggered';  // Change caption of main form
  55. end;
  56.  
  57. end.
  58.  

 

TinyPortal © 2005-2018