Sign in Join
Wiki copytemporary

Lazarus on Raspberry Pi: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-<figure>
21<img src="Lazarus_on_Raspberry_Pi_Raspian_Wheezy_version_2012-10-28.png" title="Lazarus on Raspbian Wheezy" width="200" />
3-<figcaption>Lazarus on Raspbian Wheezy</figcaption>
4-</figure>
52
63*(Raspberry Pi only)*
74
85The **Raspberry Pi** is a credit-card-sized single-board computer. It has been developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools. Raspberry Pis are also used for multiple other purposes that are as different as media servers, robotics and control engineering.
96
107The Raspberry Pi Foundation recommends [[Raspbian|the Pasperry Pi OS]] as standard operating system. Alternative systems running on RPI include RISC OS and various [[Portal:Linux|Linux]] distributions, as well as [[Portal:Android|Android]] and [[Portal:FreeBSD|FreeBSD]].
118
129Lazarus runs natively under the Raspbian operating system.
1310
1411## Installing and compiling Lazarus
1512
1613### Introduction
1714
1815Installing FPC and Lazarus on a Raspberry Pi is very little different from other Linux boxes, so please refer to [[Installing Lazarus on Linux]]. How ever, there are some RasPi particularities worth noting.
1916
2017- RasPi do not always have enough memory to build Lazarus, this affects the routine rebuild of the IDE that happens when installing packages for example. The solution is to increase swap size (below).
2118- The Lazarus SourceForge repository does not include a pre-made RasPi package.
2219- If you are using the Raspberry Pi OS, its based on Debian and Debian has quite a long release cycle. So, at any one time, the repo provided Lazarus is likely to be out of date and, occasionally, so will the FPC be.
2320- Notwithstanding the above point, at present, late 2023, the Debian Bookworm based Raspberry Pi OS has the appropriate FPC and a Lazarus that suits most people. This will change !
2421
2522### Correcting swap file size
2623
2724(Info from forum user "Thaddy", updated.) If you have RPi with memory size less then 4Gb, and you want to build Lazarus from source or use FPCUPdeluxe or just rebuild the IDE after installing a package you need to allocate at least 1G if not 2G of swap. This appears to be particularly so with Raspberry Pi OS based on Bookworm rather than Bullseye.
2825
2926To increase swap you should firstly ensure you have a couple of gig free and -
3027
3128- sudo dphys-swapfile swapoff
3229- sudo nano /etc/dphys-swapfile
3330- in the file, find CONF_SWAPSIZE and change the value to 2048 (or 1024) and save it.
3431- sudo dphys-swapfile setup
3532- sudo dphys-swapfile swapon
3633
3734You should now see the file, /var/swap, increase to 2G (or 1G). On some other operating systems, eg a "pure" debian, you may need to install the dphys-swapfile package.
3835
3936If you don't have enough memory (real memory and swap) then, your compile processes (particularly assembling) will stop and the whole machine freezes. You have been warned !
4037
4138While you are fiddling with the swap file, consider, if possible, moving the swap file from /var/swap to somewhere off the SDCard, unfortunately, SDCards are not good at the repetitive writes that happen in a swap file. Not critical but a good idea.
4239
4340If you have problems making the swap file, see this <https://forums.raspberrypi.com/viewtopic.php?p=1881546>
4441
4542### Simple installation
4643
4744Most distributions have a graphic installer of some sort, look for entries like "Add / Remove Software" in your menus. Alternatively, all systems will have a command line interface. As hinted above, its likely that your distribution will have a current FPC, if so, best to use it. More interesting is Lazarus, as it changes more frequently, consider your needs. The Raspberry Pi OS, late 2023, has Lazarus 2.2.6. While version 3.0 of Lazarus is released now, it will take awhile to make it into distro's repos. Some users will, for the time being, be quite happy with Lazarus 2.2.6. Later on, you can remove the distro supplied Lazarus 2.2.6 and build 3.0 from source yourself, its easy.
4845
4946A advantage of using the distro supplied FPC and Lazarus is that they test them, make sure everything needed is there and its very easy.
5047
5148See [the Package Manager Model](https://wiki.freepascal.org/Installing_Lazarus_on_Linux#The_Package_Manager_Model).
5249
5350### Not Quite as Simple Install
5451
5552There are two other functional alternatives for installing Lazarus, building from source and using [[fpcupdeluxe]], an application that you run on your computer to manage your FPC / Lazarus install. Its very suited to people who just want to get a working install quickly, fpcupdeluxe will do the thinking for them. Fpcupdelux will install (and manage) both FPC and Lazarus and you should use them together.
5653
5754Installing a non distro FPC is a touch more complicated still. Its [possible](https://wiki.freepascal.org/Installing_the_Free_Pascal_Compiler#Compiling_the_FPC_source.2C_using_preinstalled_FPC) to build a new FPC using an older, existing, FPC, might be a challenge for a less powerful Pi. An better option is to [download and install](https://wiki.freepascal.org/Installing_the_Free_Pascal_Compiler#Downloading_FPC_tar_balls) a tarball.
5855
5956Its quite reasonable to use the distro provided FPC and build your own Lazarus. In fact, many users have several lazarus versions installed this way.
6057
6158Building Lazarus [from source](https://wiki.freepascal.org/Installing_Lazarus_on_Linux#Build_Lazarus_from_Source) on a Raspberry Pi is no different from other Linuxes, except, perhaps, for the [[Lazarus on Raspberry Pi|memory issue]].
6259
6360<File:Lazarus> 0 9 30 4 on RPi 2.png\|Lazarus "out of the box" on Raspberry Pi 2
6461
6562### Cross compiling for the Raspberry Pi from Windows
6663
67641\. Using fpcup
6865
6966One way is to use fpcup to set up a cross compiler; follow these instructions: [[fpcup|fpcup#Linux_ARM_cross_compiler]]
7067
71682\. Using scripts
7269
7370Alternatively, for a more manual approach using batch files, you can follow these steps.
7471
75722.1 Prerequisites
7673
7774`FPC 2.7.1 or higher installed with source code`\
7875`Install the Windows version from the Linaro binutils for linux gnueabihf into %FPCPATH%/bin/win32-armhf-linux `[`1`](https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_win32.zip)
7976
80772.2 Example Windows Batch file (adapt paths as needed)
8178
8279``` bat
8380set PATH=C:\pp\bin\i386-win32;%PATH%;
8481set FPCMAKEPATH=C:/pp
8582set FPCPATH=C:/pp
8683set OUTPATH=C:/pp271
8784%FPCMAKEPATH%/bin/i386-win32/make distclean OS_TARGET=linux CPU_TARGET=arm CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" FPC=%FPCPATH%/bin/i386-win32/ppc386.exe
8885
8986%FPCMAKEPATH%/bin/i386-win32/make all OS_TARGET=linux CPU_TARGET=arm CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" FPC=%FPCPATH%/bin/i386-win32/ppc386.exe
9087if errorlevel 1 goto quit
9188%FPCMAKEPATH%/bin/i386-win32/make crossinstall CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" OS_TARGET=linux CPU_TARGET=arm FPC=%FPCPATH%/bin/i386-win32/ppc386.exe INSTALL_BASEDIR=%OUTPATH%
9289
9390:quit
9491pause
9592```
9693
9794With the resulting ppcrossarm.exe and ARM RTL you will be able to build a cross Lazarus version as usual and compile FPC projects for the Raspberry Pi and other armhf devices.
9895
9996Remember that not all - especially Windows - libraries are available for Linux arm.
10097
10198### Cross compiling for the Raspberry Pi from Linux
10299
103100Please see this page <https://wiki.freepascal.org/Cross_Compile_to_RasPi_from_Linux>
104101
105102## Accessing external hardware
106103
107-<figure>
108104<img src="rpi_pinout_all_50.png" title="Raspberry Pi pinout of external connectors" width="300" />
109-<figcaption>Raspberry Pi pinout of external connectors</figcaption>
110-</figure>
111105
112106One of the goals in the development of Raspberry Pi was to facilitate effortless access to external devices like sensors and actuators. There are many ways to access the I/O facilities from Lazarus and Free Pascal:
113107
1141081. [[Lazarus on Raspberry Pi|Direct access]] using the [[BaseUnix]] unit
1151092. Access through [[Lazarus on Raspberry Pi|encapsulated shell calls]]
1161103. Access through the [[Lazarus on Raspberry Pi|wiringPi library]].
1171114. Access through Unit [[Lazarus on Raspberry Pi|rpi_hal]].
1181125. Access through Unit [[Lazarus on Raspberry Pi|PiGpio]].
1191136. Access through the [PascalIO](https://github.com/SAmeis/pascalio) library.
1201147. Access through the [PXL](http://asphyre.net/products/pxl) library.
121115
122116### Native hardware access
123117
124118![Simple test program for accessing the GPIO port on Raspberry Pi\|thumb\|300px\|right](/wiki-images/d/d2/Testprogram_for_GPIO_on_RPI_annotated.png) ![Test circuit for GPIO access with the described program\|thumb\|300px\|right](/wiki-images/7/7c/Rpi_testcircuit_1d.png) ![Simple demo implementation of the circuit from above on a breadboard\|thumb\|300px\|right](/wiki-images/7/7e/Rpi_testcircuit_1p_annotaded.png) This method provides access to external hardware that doesn't require additional libraries. The only requirement is the BaseUnix library that is part of Free Pascal's RTL.
125119
126120#### Switching a device via the GPIO port
127121
128122The following example lists a simple program that controls the GPIO pin 17 as output to switch an LED, transistor or relays. This program contains a [[doc:lcl/stdctrls/ttogglebox.html|ToggleBox]] with name *GPIO17ToggleBox* and for logging return codes a [[doc:lcl/stdctrls/tmemo.html|TMemo]] called *LogMemo*.
129123
130124For the example, the anode of a LED has been connected with Pin 11 on the Pi's connector (corresponding to GPIO pin 17 of the BCM2835 SOC) and the LED's cathode was wired via a 68 Ohm resistor to pin 6 of the connector (GND) as previously described by Upton and Halfacree. Subsequently, the LED may be switched on and off with the application's toggle box.
131125
132126The code may at first require to be run as root, i.e. either from a root account (not recommended) or via **su**. A better option is to add the user to the gpio group, the i2c group and the spi group.
133127
134128``` bash
135129sudo adduser pi gpio
136130sudo adduser pi i2c
137131sudo adduser pi spi
138132```
139133
140134*Controlling unit:*
141135
142136``` pascal
143137unit Unit1;
144138
145139{Demo application for GPIO on Raspberry Pi}
146140{Inspired by the Python input/output demo application by Gareth Halfacree}
147141{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
148142
149143{$mode objfpc}{$H+}
150144
151145interface
152146
153147uses
154148 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
155149 Unix, BaseUnix;
156150
157151type
158152
159153 { TForm1 }
160154
161155 TForm1 = class(TForm)
162156 LogMemo: TMemo;
163157 GPIO17ToggleBox: TToggleBox;
164158 procedure FormActivate(Sender: TObject);
165159 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
166160 procedure GPIO17ToggleBoxChange(Sender: TObject);
167161 private
168162 { private declarations }
169163 public
170164 { public declarations }
171165 end;
172166
173167const
174168 PIN_17: PChar = '17';
175169 PIN_ON: PChar = '1';
176170 PIN_OFF: PChar = '0';
177171 OUT_DIRECTION: PChar = 'out';
178172
179173var
180174 Form1: TForm1;
181175 gReturnCode: longint; {stores the result of the IO operation}
182176
183177implementation
184178
185179{$R *.lfm}
186180
187181{ TForm1 }
188182
189183procedure TForm1.FormActivate(Sender: TObject);
190184var
191185 fileDesc: integer;
192186begin
193187 { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
194188 try
195189 fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
196190 gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
197191 LogMemo.Lines.Add(IntToStr(gReturnCode));
198192 finally
199193 gReturnCode := fpclose(fileDesc);
200194 LogMemo.Lines.Add(IntToStr(gReturnCode));
201195 end;
202196 { Set SoC pin 17 as output: }
203197 try
204198 fileDesc := fpopen('/sys/class/gpio/gpio17/direction', O_WrOnly);
205199 gReturnCode := fpwrite(fileDesc, OUT_DIRECTION[0], 3);
206200 LogMemo.Lines.Add(IntToStr(gReturnCode));
207201 finally
208202 gReturnCode := fpclose(fileDesc);
209203 LogMemo.Lines.Add(IntToStr(gReturnCode));
210204 end;
211205end;
212206
213207procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
214208var
215209 fileDesc: integer;
216210begin
217211 { Free SoC pin 17: }
218212 try
219213 fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
220214 gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
221215 LogMemo.Lines.Add(IntToStr(gReturnCode));
222216 finally
223217 gReturnCode := fpclose(fileDesc);
224218 LogMemo.Lines.Add(IntToStr(gReturnCode));
225219 end;
226220end;
227221
228222procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
229223var
230224 fileDesc: integer;
231225begin
232226 if GPIO17ToggleBox.Checked then
233227 begin
234228 { Swith SoC pin 17 on: }
235229 try
236230 fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
237231 gReturnCode := fpwrite(fileDesc, PIN_ON[0], 1);
238232 LogMemo.Lines.Add(IntToStr(gReturnCode));
239233 finally
240234 gReturnCode := fpclose(fileDesc);
241235 LogMemo.Lines.Add(IntToStr(gReturnCode));
242236 end;
243237 end
244238 else
245239 begin
246240 { Switch SoC pin 17 off: }
247241 try
248242 fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
249243 gReturnCode := fpwrite(fileDesc, PIN_OFF[0], 1);
250244 LogMemo.Lines.Add(IntToStr(gReturnCode));
251245 finally
252246 gReturnCode := fpclose(fileDesc);
253247 LogMemo.Lines.Add(IntToStr(gReturnCode));
254248 end;
255249 end;
256250end;
257251
258252end.
259253```
260254
261255*Main program:*
262256
263257``` pascal
264258program io_test;
265259
266260{$mode objfpc}{$H+}
267261
268262uses
269263 {$IFDEF UNIX}{$IFDEF UseCThreads}
270264 cthreads,
271265 {$ENDIF}{$ENDIF}
272266 Interfaces, // this includes the LCL widgetset
273267 Forms, Unit1
274268 { you can add units after this };
275269
276270{$R *.res}
277271
278272begin
279273 Application.Initialize;
280274 Application.CreateForm(TForm1, Form1);
281275 Application.Run;
282276end.
283277```
284278
285279#### Reading the status of a pin
286280
287281![Demo program for reading the status of a GPIO pin\|thumb\|300px\|right](/wiki-images/7/73/2013-04-28-193243_1280x1024_scrot.png) ![Test circuit for GPIO access with the described program\|thumb\|300px\|right](/wiki-images/f/f4/Rpi_testcircuit_2d.png) ![Possible implementation of this test circuit\|thumb\|300px\|right](/wiki-images/2/2f/Rpi_testcircuit_2p_annotaded.png)
288282
289283Of course it is also possible to read the status of e.g. a switch that is connected to the GPIO port.
290284
291285The following simple example is very similar to the previous one. It controls the GPIO pin 18 as input for a binary device like a switch, transistor or relais. This program contains a [[doc:lcl/stdctrls/tcheckbox.html|CheckBox]] with name *GPIO18CheckBox* and for logging return codes a [[doc:lcl/stdctrls/tmemo.html|TMemo]] called *LogMemo*.
292286
293287For the example, one pole of a push-button has been connected to Pin 12 on the Pi's connector (corresponding to GPIO pin 18 of the BCM2835 SOC) and via a 10k Ohm pull-up resistor with pin 1 (+3.3V, see wiring diagram). The other pole has been wired to pin 6 of the connector (GND). The program senses the status of the button and correspondingly switches the checkbox on or off, respectively.
294288
295289Note that the potential of pin 18 is high if the button is released (by virtue of the connection to pin 1 via the pull-up resistor) and low if it is pressed (since in this situation pin 18 is connected to GND via the switch). Therefore, the GPIO pin signals 0 if the button is pressed and 1 if it is released.
296290
297291This program has again to be executed as root.
298292
299293*Controlling unit:*
300294
301295``` pascal
302296unit Unit1;
303297
304298{Demo application for GPIO on Raspberry Pi}
305299{Inspired by the Python input/output demo application by Gareth Halfacree}
306300{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
307301
308302{This application reads the status of a push-button}
309303
310304{$mode objfpc}{$H+}
311305
312306interface
313307
314308uses
315309 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
316310 ButtonPanel, Unix, BaseUnix;
317311
318312type
319313
320314 { TForm1 }
321315
322316 TForm1 = class(TForm)
323317 ApplicationProperties1: TApplicationProperties;
324318 GPIO18CheckBox: TCheckBox;
325319 LogMemo: TMemo;
326320 procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
327321 procedure FormActivate(Sender: TObject);
328322 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
329323 private
330324 { private declarations }
331325 public
332326 { public declarations }
333327 end;
334328
335329const
336330 PIN_18: PChar = '18';
337331 IN_DIRECTION: PChar = 'in';
338332
339333var
340334 Form1: TForm1;
341335 gReturnCode: longint; {stores the result of the IO operation}
342336
343337implementation
344338
345339{$R *.lfm}
346340
347341{ TForm1 }
348342
349343procedure TForm1.FormActivate(Sender: TObject);
350344var
351345 fileDesc: integer;
352346begin
353347 { Prepare SoC pin 18 (pin 12 on GPIO port) for access: }
354348 try
355349 fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
356350 gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
357351 LogMemo.Lines.Add(IntToStr(gReturnCode));
358352 finally
359353 gReturnCode := fpclose(fileDesc);
360354 LogMemo.Lines.Add(IntToStr(gReturnCode));
361355 end;
362356 { Set SoC pin 18 as input: }
363357 try
364358 fileDesc := fpopen('/sys/class/gpio/gpio18/direction', O_WrOnly);
365359 gReturnCode := fpwrite(fileDesc, IN_DIRECTION[0], 2);
366360 LogMemo.Lines.Add(IntToStr(gReturnCode));
367361 finally
368362 gReturnCode := fpclose(fileDesc);
369363 LogMemo.Lines.Add(IntToStr(gReturnCode));
370364 end;
371365end;
372366
373367procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
374368var
375369 fileDesc: integer;
376370 buttonStatus: string[1] = '1';
377371begin
378372 try
379373 { Open SoC pin 18 (pin 12 on GPIO port) in read-only mode: }
380374 fileDesc := fpopen('/sys/class/gpio/gpio18/value', O_RdOnly);
381375 if fileDesc > 0 then
382376 begin
383377 { Read status of this pin (0: button pressed, 1: button released): }
384378 gReturnCode := fpread(fileDesc, buttonStatus[1], 1);
385379 LogMemo.Lines.Add(IntToStr(gReturnCode) + ': ' + buttonStatus);
386380 LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
387381 if buttonStatus = '0' then
388382 GPIO18CheckBox.Checked := true
389383 else
390384 GPIO18CheckBox.Checked := false;
391385 end;
392386 finally
393387 { Close SoC pin 18 (pin 12 on GPIO port) }
394388 gReturnCode := fpclose(fileDesc);
395389 LogMemo.Lines.Add(IntToStr(gReturnCode));
396390 LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
397391 end;
398392end;
399393
400394procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
401395var
402396 fileDesc: integer;
403397begin
404398 { Free SoC pin 18: }
405399 try
406400 fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
407401 gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
408402 LogMemo.Lines.Add(IntToStr(gReturnCode));
409403 finally
410404 gReturnCode := fpclose(fileDesc);
411405 LogMemo.Lines.Add(IntToStr(gReturnCode));
412406 end;
413407end;
414408
415409end.
416410```
417411
418412The main program is identical to that of the example from above.
419413
420414### Hardware access via encapsulated shell calls
421415
422416Another way to access the hardware is by encapsulating terminal commands. This is achieved by using the [[Executing External Programs|fpsystem]] function. This method gives access to functions that are not supported by the BaseUnix unit. The following code implements a program that has the same functionality as the program resulting from the first listing above.
423417
424418*Controlling unit:*
425419
426420``` pascal
427421unit Unit1;
428422
429423{Demo application for GPIO on Raspberry Pi}
430424{Inspired by the Python input/output demo application by Gareth Halfacree}
431425{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
432426
433427{$mode objfpc}{$H+}
434428
435429interface
436430
437431uses
438432 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Unix;
439433
440434type
441435
442436 { TForm1 }
443437
444438 TForm1 = class(TForm)
445439 LogMemo: TMemo;
446440 GPIO17ToggleBox: TToggleBox;
447441 procedure FormActivate(Sender: TObject);
448442 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
449443 procedure GPIO17ToggleBoxChange(Sender: TObject);
450444 private
451445 { private declarations }
452446 public
453447 { public declarations }
454448 end;
455449
456450var
457451 Form1: TForm1;
458452 gReturnCode: longint; {stores the result of the IO operation}
459453
460454implementation
461455
462456{$R *.lfm}
463457
464458{ TForm1 }
465459
466460procedure TForm1.FormActivate(Sender: TObject);
467461begin
468462 { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
469463 gReturnCode := fpsystem('echo "17" > /sys/class/gpio/export');
470464 LogMemo.Lines.Add(IntToStr(gReturnCode));
471465 { Set SoC pin 17 as output: }
472466 gReturnCode := fpsystem('echo "out" > /sys/class/gpio/gpio17/direction');
473467 LogMemo.Lines.Add(IntToStr(gReturnCode));
474468end;
475469
476470procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
477471begin
478472 { Free SoC pin 17: }
479473 gReturnCode := fpsystem('echo "17" > /sys/class/gpio/unexport');
480474 LogMemo.Lines.Add(IntToStr(gReturnCode));
481475end;
482476
483477procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
484478begin
485479 if GPIO17ToggleBox.Checked then
486480 begin
487481 { Swith SoC pin 17 on: }
488482 gReturnCode := fpsystem('echo "1" > /sys/class/gpio/gpio17/value');
489483 LogMemo.Lines.Add(IntToStr(gReturnCode));
490484 end
491485 else
492486 begin
493487 { Switch SoC pin 17 off: }
494488 gReturnCode := fpsystem('echo "0" > /sys/class/gpio/gpio17/value');
495489 LogMemo.Lines.Add(IntToStr(gReturnCode));
496490 end;
497491end;
498492
499493end.
500494```
501495
502496The main program is identical to that of the example above. This program has to be executed with root privileges, too.
503497
504498### wiringPi procedures and functions
505499
506500Alex Schaller's wrapper unit for Gordon Henderson's Arduino compatible wiringPi library provides a numbering scheme that resembles that of Arduino boards.
507501
508502**Function wiringPiSetup:longint:** Initializes wiringPi system using the wiringPi pin numbering scheme.
509503
510504**Procedure wiringPiGpioMode(mode:longint):** Initializes wiringPi system with the Broadcom GPIO pin numbering scheme.
511505
512506**Procedure pullUpDnControl(pin:longint;** pud:longint): controls the internal pull-up/down resistors on a GPIO pin.
513507
514508**Procedure pinMode(pin:longint; mode:longint):** sets the mode of a pin to either INPUT, OUTPUT, or PWM_OUTPUT.
515509
516510**Procedure digitalWrite(pin:longint; value:longint):** sets an output bit.
517511
518512**Procedure pwmWrite(pin:longint; value:longint):** sets an output PWM value between 0 and 1024.
519513
520514**Function digitalRead(pin:longint):longint:** reads the value of a given Pin, returning 1 or 0.
521515
522516**Procedure delay(howLong:dword):** waits for at least howLong milliseconds.
523517
524518**Procedure delayMicroseconds(howLong:dword):** waits for at least howLong microseconds.
525519
526520**Function millis:dword:** returns the number of milliseconds since the program called one of the wiringPiSetup functions.
527521
528522### rpi_hal-Hardware Abstraction Library (GPIO, I2C and SPI functions and procedures)
529523
530524This Unit with around 1700 Lines of Code provided by Stefan Fischer, delivers procedures and functions to access the rpi HW I2C, SPI and GPIO:
531525
532526Just an excerpt of the available functions and procedures:
533527
534528**procedure gpio_set_pin (pin:longword;highlevel:boolean);** { Set RPi GPIO pin to high or low level; Speed @ 700MHz -\> 0.65MHz }
535529
536530**function gpio_get_PIN (pin:longword):boolean;** { Get RPi GPIO pin Level is true when Pin level is '1'; false when '0'; Speed @ 700MHz -\> 1.17MHz }
537531
538532**procedure gpio_set_input (pin:longword);** { Set RPi GPIO pin to input direction }
539533
540534**procedure gpio_set_output(pin:longword);** { Set RPi GPIO pin to output direction }
541535
542536**procedure gpio_set_alt (pin,altfunc:longword);** { Set RPi GPIO pin to alternate function nr. 0..5 }
543537
544538**procedure gpio_set_gppud (mask:longword);** { set RPi GPIO Pull-up/down Register (GPPUD) with mask }
545539
546540...
547541
548542**function rpi_snr :string;** { delivers SNR: 0000000012345678 }
549543
550544**function rpi_hw :string;** { delivers Processor Type: BCM2708 }
551545
552546**function rpi_proc:string;** { ARMv6-compatible processor rev 7 (v6l) }
553547
554548...
555549
556550**function i2c_bus_write(baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : integer;**
557551
558552**function i2c_bus_read (baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : integer;**
559553
560554**function i2c_string_read(baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : string;**
561555
562556**function i2c_string_write(baseadr,reg:word; s:string; testnr:integer) : integer;**
563557
564558...
565559
566560**procedure SPI_Write(devnum:byte; reg,data:word);**
567561
568562**function SPI_Read(devnum:byte; reg:word) : byte;**
569563
570564**procedure SPI_BurstRead2Buffer (devnum,start_reg:byte; xferlen:longword);**
571565
572566**procedure SPI_BurstWriteBuffer (devnum,start_reg:byte; xferlen:longword);** { Write 'len' Bytes from Buffer SPI Dev startig at address 'reg' }
573567
574568...
575569
576570*Test Program (testrpi.pas):*
577571
578572``` pascal
579573//Simple Test program, which is using rpi_hal;
580574
581575 program testrpi;
582576 uses rpi_hal;
583577 begin
584578 writeln('Show CPU-Info, RPI-HW-Info and Registers:');
585579 rpi_show_all_info;
586580 writeln('Let Status LED Blink. Using GPIO functions:');
587581 GPIO_PIN_TOGGLE_TEST;
588582 writeln('Test SPI Read function. (piggy back board with installed RFM22B Module is required!)');
589583 Test_SPI;
590584 end.
591585```
592586
593587### PiGpio Low-level native pascal unit (GPIO control instead of wiringPi c library)
594588
595589*This Unit (pigpio.pas[2](https://docs.google.com/file/d/0B-b-5ooIWPvGN1BIcEJzRDgyeUE/edit?usp=sharing)) with 270 Lines of Code provided by Gabor Szollosi, works very fast (for ex. GPIO pin output switching frequency 8 MHz) :*
596590
597591``` pascal
598592
599593unit PiGpio;
600594{
601595 BCM2835 GPIO Registry Driver, also can use to manipulate cpu other registry areas
602596
603597 This code is tested only Broadcom bcm2835 cpu, different arm cpus may need different
604598 gpio driver implementation
605599
606600 2013 Gabor Szollosi
607601}
608602{$mode objfpc}{$H+}
609603
610604interface
611605
612606uses
613607 Classes, SysUtils;
614608
615609const
616610 REG_GPIO = $3F000;// bcm2835 gpio register 0x2000 0000 (RPi1), 0x3F00 0000 (RPi2)
617611 // new fpMap uses page offset, one page is 4096 bytes = 0x1000 so simply calculate 0x2000 0000 / 0x1000 = 0x2000 0
618612 PAGE_SIZE = 4096;
619613 BLOCK_SIZE = 4096;
620614 // The BCM2835 has 54 GPIO pins.
621615 // BCM2835 data sheet, Page 90 onwards.
622616 // There are 6 control registers, each control the functions of a block
623617 // of 10 pins.
624618
625619 CLOCK_BASE = (REG_GPIO + $101);
626620 GPIO_BASE = (REG_GPIO + $200);
627621 GPIO_PWM = (REG_GPIO + $20C);
628622
629623 INPUT = 0;
630624 OUTPUT = 1;
631625 PWM_OUTPUT = 2;
632626 LOW = False;
633627 HIGH = True;
634628 PUD_OFF = 0;
635629 PUD_DOWN = 1;
636630 PUD_UP = 2;
637631
638632 // PWM
639633
640634 PWM_CONTROL = 0;
641635 PWM_STATUS = 4;
642636 PWM0_RANGE = 16;
643637 PWM0_DATA = 20;
644638 PWM1_RANGE = 32;
645639 PWM1_DATA = 36;
646640
647641 PWMCLK_CNTL = 160;
648642 PWMCLK_DIV = 164;
649643
650644 PWM1_MS_MODE = $8000; // Run in MS mode
651645 PWM1_USEFIFO = $2000; // Data from FIFO
652646 PWM1_REVPOLAR = $1000; // Reverse polarity
653647 PWM1_OFFSTATE = $0800; // Ouput Off state
654648 PWM1_REPEATFF = $0400; // Repeat last value if FIFO empty
655649 PWM1_SERIAL = $0200; // Run in serial mode
656650 PWM1_ENABLE = $0100; // Channel Enable
657651
658652 PWM0_MS_MODE = $0080; // Run in MS mode
659653 PWM0_USEFIFO = $0020; // Data from FIFO
660654 PWM0_REVPOLAR = $0010; // Reverse polarity
661655 PWM0_OFFSTATE = $0008; // Ouput Off state
662656 PWM0_REPEATFF = $0004; // Repeat last value if FIFO empty
663657 PWM0_SERIAL = $0002; // Run in serial mode
664658 PWM0_ENABLE = $0001; // Channel Enable
665659
666660type
667661
668662 { TIoPort }
669663
670664 TIoPort = class // IO bank object
671665 private //
672666
673667 //function get_pinDirection(aPin: TGpIoPin): TGpioPinConf;
674668
675669 public
676670 FGpio: ^LongWord;
677671 FClk: ^LongWord;
678672 FPwm: ^LongWord;
679673 procedure SetPinMode(gpin, mode: byte);
680674 function GetBit(gpin : byte):boolean;inline; // gets pin bit}
681675 procedure ClearBit(gpin : byte);inline;// write pin to 0
682676 procedure SetBit(gpin : byte);inline;// write pin to 1
683677 procedure SetPullMode(gpin, mode: byte);
684678 procedure PwmWrite(gpin : byte; value : LongWord);inline;// write pin to pwm value
685679 end;
686680
687681 { TIoDriver }
688682
689683 TIoDriver = class
690684 private
691685
692686 public
693687 destructor Destroy;override;
694688 function MapIo:boolean;// creates io memory mapping
695689 procedure UnmapIoRegisrty(FMap: TIoPort);// close io memory mapping
696690 function CreatePort(PortGpio, PortClk, PortPwm: LongWord):TIoPort; // create new IO port
697691 end;
698692
699693var
700694
701695 fd: integer;// /dev/mem file handle
702696procedure delayNanoseconds (howLong : LongWord);
703697
704698implementation
705699
706700uses
707701 baseUnix, Unix;
708702
709703procedure delayNanoseconds (howLong : LongWord);
710704var
711705 sleeper, dummy : timespec;
712706begin
713707 sleeper.tv_sec := 0 ;
714708 sleeper.tv_nsec := howLong ;
715709 fpnanosleep (@sleeper,@dummy) ;
716710end;
717711{ TIoDriver }
718712//*******************************************************************************
719713destructor TIoDriver.Destroy;
720714begin
721715 inherited Destroy;
722716end;
723717//*******************************************************************************
724718function TIoDriver.MapIo: boolean;
725719begin
726720 Result := True;
727721 fd := fpopen('/dev/mem', O_RdWr or O_Sync); // Open the master /dev/memory device
728722 if fd < 0 then
729723 begin
730724 Result := False; // unsuccessful memory mapping
731725 end;
732726 //
733727end;
734728//*******************************************************************************
735729procedure TIoDriver.UnmapIoRegisrty(FMap:TIoPort);
736730begin
737731 if FMap.FGpio <> nil then
738732 begin
739733 fpMUnmap(FMap.FGpio,PAGE_SIZE);
740734 FMap.FGpio := Nil;
741735 end;
742736 if FMap.FClk <> nil then
743737 begin
744738 fpMUnmap(FMap.FClk,PAGE_SIZE);
745739 FMap.FClk := Nil;
746740 end;
747741 if FMap.FPwm <> nil then
748742 begin
749743 fpMUnmap(FMap.FPwm ,PAGE_SIZE);
750744 FMap.FPwm := Nil;
751745 end;
752746end;
753747//*******************************************************************************
754748function TIoDriver.CreatePort(PortGpio, PortClk, PortPwm: LongWord): TIoPort;
755749begin
756750 Result := TIoPort.Create;// new io port, pascal calls new fpMap, where offst is page sized 4096 bytes!!!
757751 Result.FGpio := FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortGpio); // port config gpio memory
758752 Result.FClk:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortClk);; // port clk
759753 Result.FPwm:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortPwm);; // port pwm
760754end;
761755//*******************************************************************************
762756procedure TIoPort.SetPinMode(gpin, mode: byte);
763757var
764758 fSel, shift, alt : byte;
765759 gpiof, clkf, pwmf : ^LongWord;
766760begin
767761 fSel := (gpin div 10)*4 ; //Select Gpfsel 0 to 5 register
768762 shift := (gpin mod 10)*3 ; //0-9 pin shift
769763 gpiof := Pointer(LongWord(Self.FGpio)+fSel);
770764 if (mode = INPUT) then
771765 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) //7 shl shift komplemens - Sets bits to zero = input
772766 else if (mode = OUTPUT) then
773767 begin
774768 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (1 shl shift);
775769 end
776770 else if (mode = PWM_OUTPUT) then
777771 begin
778772 Case gpin of
779773 12,13,40,41,45 : alt:= 4 ;
780774 18,19 : alt:= 2 ;
781775 else alt:= 0 ;
782776 end;
783777 If alt > 0 then
784778 begin
785779 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (alt shl shift);
786780 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
787781 clkf^ := $5A000011 or (1 shl 5) ; //stop clock
788782 delayNanoseconds(200);
789783 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_DIV);
790784 clkf^ := $5A000000 or (32 shl 12) ; // set pwm clock div to 32 (19.2/3 = 600KHz)
791785 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
792786 clkf^ := $5A000011 ; //start clock
793787 Self.ClearBit(gpin);
794788 pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
795789 pwmf^ := 0 ; // Disable PWM
796790 delayNanoseconds(200);
797791 pwmf := Pointer(LongWord(Self.FPwm)+PWM0_RANGE);
798792 pwmf^ := $400 ; //max: 1023
799793 delayNanoseconds(200);
800794 pwmf := Pointer(LongWord(Self.FPwm)+PWM1_RANGE);
801795 pwmf^ := $400 ; //max: 1023
802796 delayNanoseconds(200);
803797 // Enable PWMs
804798 pwmf := Pointer(LongWord(Self.FPwm)+PWM0_DATA);
805799 pwmf^ := 0 ; //start value
806800 pwmf := Pointer(LongWord(Self.FPwm)+PWM1_DATA);
807801 pwmf^ := 0 ; //start value
808802 pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
809803 pwmf^ := PWM0_ENABLE or PWM1_ENABLE ;
810804 end;
811805 end;
812806end;
813807//*******************************************************************************
814808procedure TIoPort.SetBit(gpin : byte);
815809var
816810 gpiof : ^LongWord;
817811begin
818812 gpiof := Pointer(LongWord(Self.FGpio) + 28 + (gpin shr 5) shl 2);
819813 gpiof^ := 1 shl gpin;
820814end;
821815//*******************************************************************************
822816procedure TIoPort.ClearBit(gpin : byte);
823817var
824818 gpiof : ^LongWord;
825819begin
826820 gpiof := Pointer(LongWord(Self.FGpio) + 40 + (gpin shr 5) shl 2);
827821 gpiof^ := 1 shl gpin;
828822end;
829823//*******************************************************************************
830824function TIoPort.GetBit(gpin : byte):boolean;
831825var
832826 gpiof : ^LongWord;
833827begin
834828 gpiof := Pointer(LongWord(Self.FGpio) + 52 + (gpin shr 5) shl 2);
835829 if (gpiof^ and (1 shl gpin)) = 0 then Result := False else Result := True;
836830end;
837831//*******************************************************************************
838832procedure TIoPort.SetPullMode(gpin, mode: byte);
839833var
840834 pudf, pudclkf : ^LongWord;
841835begin
842836 pudf := Pointer(LongWord(Self.FGpio) + 148 );
843837 pudf^ := mode; //mode = 0, 1, 2 :Off, Down, Up
844838 delayNanoseconds(200);
845839 pudclkf := Pointer(LongWord(Self.FGpio) + 152 + (gpin shr 5) shl 2);
846840 pudclkf^ := 1 shl gpin ;
847841 delayNanoseconds(200);
848842 pudf^ := 0 ;
849843 pudclkf^ := 0 ;
850844end;
851845//*******************************************************************************
852846procedure TIoPort.PwmWrite(gpin : byte; value : Longword);
853847var
854848 pwmf : ^LongWord;
855849 port : byte;
856850begin
857851 Case gpin of
858852 12,18,40 : port:= PWM0_DATA ;
859853 13,19,41,45 : port:= PWM1_DATA ;
860854 else exit;
861855 end;
862856 pwmf := Pointer(LongWord(Self.FPwm) + port);
863857 pwmf^ := value and $FFFFFBFF; // $400 complemens
864858end;
865859//*******************************************************************************
866860end.
867861```
868862
869863*Controlling Lazarus unit:(Project files[3](https://drive.google.com/folderview?id=0B-b-5ooIWPvGU043ZTZ0cUc2YkE&usp=sharing))*
870864
871865``` pascal
872866unit Unit1;
873867
874868{Demo application for GPIO on Raspberry Pi}
875869{Inspired by the Python input/output demo application by Gareth Halfacree}
876870{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
877871
878872{$mode objfpc}{$H+}
879873
880874interface
881875
882876uses
883877 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
884878 ExtCtrls, Unix, PiGpio;
885879
886880type
887881
888882 { TForm1 }
889883
890884 TForm1 = class(TForm)
891885 GPIO25In: TButton;
892886 SpeedButton: TButton;
893887 LogMemo: TMemo;
894888 GPIO23switch: TToggleBox;
895889 Timer1: TTimer;
896890 GPIO18Pwm: TToggleBox;
897891 Direction: TToggleBox;
898892 procedure DirectionChange(Sender: TObject);
899893 procedure GPIO18PwmChange(Sender: TObject);
900894 procedure GPIO25InClick(Sender: TObject);
901895 procedure FormActivate(Sender: TObject);
902896 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
903897 procedure GPIO23switchChange(Sender: TObject);
904898 procedure SpeedButtonClick(Sender: TObject);
905899 procedure Timer1Timer(Sender: TObject);
906900 private
907901 { private declarations }
908902 public
909903 { public declarations }
910904 end;
911905
912906const
913907 INPUT = 0;
914908 OUTPUT = 1;
915909 PWM_OUTPUT = 2;
916910 LOW = False;
917911 HIGH = True;
918912 PUD_OFF = 0;
919913 PUD_DOWN = 1;
920914 PUD_UP = 2;
921915 // Convert Raspberry Pi P1 pins (Px) to GPIO port
922916 P3 = 0;
923917 P5 = 1;
924918 P7 = 4;
925919 P8 = 14;
926920 P10 = 15;
927921 P11 = 17;
928922 P12 = 18;
929923 P13 = 21;
930924 P15 = 22;
931925 P16 = 23;
932926 P18 = 24;
933927 P19 = 10;
934928 P21 = 9;
935929 P22 = 25;
936930 P23 = 11;
937931 P24 = 8;
938932 P26 = 7;
939933
940934var
941935 Form1: TForm1;
942936 GPIO_Driver: TIoDriver;
943937 GpF: TIoPort;
944938 PWM :Boolean;
945939 i, d : integer;
946940 Pin,Pout,Ppwm : byte;
947941
948942implementation
949943
950944{$R *.lfm}
951945
952946{ TForm1 }
953947
954948procedure TForm1.FormActivate(Sender: TObject);
955949begin
956950 if not GPIO_Driver.MapIo then
957951 begin
958952 LogMemo.Lines.Add('Error mapping gpio registry');
959953 end
960954 else
961955 begin
962956 GpF := GpIo_Driver.CreatePort(GPIO_BASE, CLOCK_BASE, GPIO_PWM);
963957 end ;
964958 Timer1.Enabled:= True;
965959 Timer1.Interval:= 25; //25 ms controll interval
966960 Pin := P22;
967961 Pout := P16;
968962 Ppwm := P12;
969963 i:=1;
970964 GpF.SetPinMode(Pout,OUTPUT);
971965 GpF.SetPinMode(Pin,INPUT);
972966 GpF.SetPullMode(Pin,PUD_Up); // Input PullUp High level
973967end;
974968
975969procedure TForm1.GPIO25InClick(Sender: TObject);
976970begin
977971 If GpF.GetBit(Pin) then LogMemo.Lines.Add('In: '+IntToStr(1))
978972 else LogMemo.Lines.Add('In: '+IntToStr(0));
979973end;
980974
981975procedure TForm1.GPIO18PwmChange(Sender: TObject);
982976begin
983977 if GPIO18Pwm.Checked then
984978 begin
985979 GpF.SetPinMode(Ppwm,PWM_OUTPUT);
986980 PWM := True; //PWM on
987981 end
988982 else
989983 begin
990984 GpF.SetPinMode(Ppwm,INPUT);
991985 PWM := False; //PWM off
992986 end;
993987end;
994988
995989procedure TForm1.DirectionChange(Sender: TObject);
996990begin
997991 if Direction.Checked then d:=10 else d:=-10;
998992end;
999993
1000994
1001995procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
1002996begin
1003997 GpF.SetPinMode(Ppwm,INPUT);
1004998 GpF.ClearBit(Pout);
1005999 GpIo_Driver.UnmapIoRegisrty(GpF);
10061000end;
10071001
10081002procedure TForm1.GPIO23switchChange(Sender: TObject);
10091003
10101004Begin
10111005 Timer1.Enabled := False;
10121006 if GPIO23switch.Checked then
10131007 begin
10141008 GpF.SetBit(Pout); //Turn LED on
10151009 end
10161010 else
10171011 begin
10181012 GpF.ClearBit(Pout); //Turn LED off
10191013 end;
10201014 Timer1.Enabled := True;
10211015end;
10221016
10231017procedure TForm1.SpeedButtonClick(Sender: TObject);
10241018var
10251019 i,p,k,v: longint;
10261020 ido:TDateTime;
10271021begin
10281022 ido:= Time;
10291023 k:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
10301024 LogMemo.Lines.Add('Start: '+TimeToStr(ido));
10311025 p:=10000000 ;
10321026 For i:=1 to p do Begin
10331027 GpF.SetBit(P16);
10341028 GpF.ClearBit(P16);
10351029 end;
10361030 ido:= Time;
10371031 v:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
10381032 LogMemo.Lines.Add('Stop: '+TimeToStr(ido)+' Frequency: '+
10391033 IntToStr(p div (v-k))+' kHz');
10401034end;
10411035
10421036procedure TForm1.Timer1Timer(Sender: TObject);
10431037begin
10441038 If PWM then Begin
10451039 If (d > 0) and (i+d < 1024) then begin
10461040 i:=i+d;
10471041 GpF.PwmWrite(Ppwm,i);
10481042 end ;
10491043 If (d < 0) and (i+d > -1) then begin
10501044 i:=i+d;
10511045 GpF.PwmWrite(Ppwm,i);
10521046 end;
10531047 end;
10541048end;
10551049
10561050
10571051end.
10581052```
10591053
10601054### PXL (Platform eXtended Library) for low level native access to GPIO, I²C, SPI, PWM, UART, V4L2, displays and sensors
10611055
10621056- Easy and fast access to GPIO, I²C, SPI, PWM, UART and high precision CPU timer.
10631057- V4L2 video/image capture using onboard and USB cameras. Serial cameras such as VC0706 and LSY201.
10641058- OpenGL ES hardware rendering with and without X server. Software rendering.
10651059- I²C and SPI displays such as SSD1306, SSD1351, PCB8544 (Nokia), HX8357 and ILI9340.
10661060- Character LCDs with direct pin wiring.
10671061- Support for Software SPI and UART (bit-banging).
10681062- Support for SC16IS7x0 (UART controller connected via I²C or SPI), including extra GPIO pins.
10691063- Support for sensors such as BMP180, DHT22, L3GD20, LSM303 and SHT10.
10701064- Other features like networking, math, image transformation, effects, drawing primitives...
10711065
10721066*More info and download of [PXL library](http://asphyre.net/products/pxl).*
10731067
10741068*The PinDrive property is not implemented in the latest download from Asphyre so I am posting the code for my implementation in case anyone needs it. I found that the definition for TPinDrive is incorrect for the BCM2837 chip so I added some code to change it. This could be accomplished more easily by changing the definition but that file could conceivably be used for multiple chips (and I don't control the code) so I made all changes in the code to set the drive mode.*
10751069
10761070``` pascal
10771071
10781072procedure TFastGPIO.SetPinDrive(const Pin: TPinIdentifier; const Value: TPinDrive);
10791073const
10801074 GPPUDadr = $94;
10811075 GPPclkadr = $98;
10821076type
10831077 TBCM28PinDrive = (drvNone, drvPullDown, drvPullUp);
10841078var
10851079 dValue: TBCM28PinDrive;
10861080 PinBCM: TPinIdentifier;
10871081 GPPUD, GPPclk: Pointer;
10881082begin
10891083 case Value of
10901084 TPinDrive.PullUp: dValue := TBCM28PinDrive.drvPullDown;
10911085 TPinDrive.PullDown: dValue := TBCM28PinDrive.drvPullUp;
10921086 else
10931087 dValue := TBCM28PinDrive.drvNone;
10941088
10951089 PinBCM := ProcessPinNumber(Pin);
10961090
10971091 GPPUD := GetOffsetPointer(GPPUDadr);
10981092 WriteMemSafe(GPPUD, Cardinal(dValue));
10991093 FSystemCore.MicroDelay(1);
11001094
11011095 GPPclk := GetOffsetPointer(GPPclkadr + (Cardinal(PinBCM) div 32) * 4);
11021096 WriteMemSafe(GPPclk, 1 shl (PinBCM mod 32));
11031097 FSystemCore.MicroDelay(1);
11041098
11051099 WriteMemSafe(GPPUD, 0);
11061100 WriteMemSafe(GPPclk, 0);
11071101end;
11081102```
11091103
11101104## References
11111105
11121106- Eben Upton and Gareth Halfacree. Raspberry Pi User Guide. John Wiley and Sons, Chichester 2012, ISBN 111846446X
11131107- B. J. Rao (2013) The Raspberry Pi, Pi Vision and Lazarus/FPC. [Blaise Pascal Magazine](http://www.blaisepascal.eu). 29: 14-21.
11141108
11151109## External and Other Links
11161110
11171111- If you want to install the latest stable release of fpc and, additional and isolated, the trunk fpc compiler: you can read the following guide.
11181112
11191113It was written using gentoo but this guide will be useful with any distro: [[Install fpc on Raspberry with Gentoo]] (very out of date)
11201114
11211115- [Raspberry Pi Foundation](http://www.raspberrypi.org)
11221116- [Raspberry Pi Spy: Raspberry Pi tutorials, scripts, help and downloads](http://www.raspberrypi-spy.co.uk)
11231117- [Lazarus wrapper unit for Gordon Henderson's wiringPi C library](http://www.lazarus.freepascal.org/index.php/topic,17404.0.html)
11241118- [Another wiringPi wrapper with waitForInterrupt() and wiringPiISR()](https://github.com/laz2wiringpi/laz2wiringpi)
11251119- [Yet another wiringPi wrapper with waitForInterrupt(), wiringPiISR(), i2c, spi and serial](https://forum.lazarus.freepascal.org/index.php/topic,17404.msg405237.html#msg405237)
11261120- [Pin layout of the wiringPi library](https://projects.drogon.net/raspberry-pi/wiringpi/pins/)
11271121- [wiringPi fork updated for latest hardware](https://github.com/WiringPi/WiringPi)
11281122- [Additional information on Lazarus and Raspberry Pi at eLinux.org](http://www.elinux.org/Lazarus_on_RPi)
11291123- [Getting Started with Pascal on the Pi](http://www.pp4s.co.uk/main/gs-pi-intro.html) (noted dead link in late 2023)
11301124- [Getting Started with Led, Switch and DC motor on Pi](http://www.pp4s.co.uk/main/gs-pi-gpio-intro.html) (noted dead link in late 2023)
11311125- [lazi2cdev - General i2c with drivers for ADS1015 ADC, MCP23017 IO, MCP4725 DAC, PCA9685 PWM and HD44780 LCD](https://github.com/laz2wiringpi/lazI2cdev)
11321126- [Lazberry Pi: Comprehensive information on Lazarus on the Raspberry Pi computer](http://superbitysoft.co.uk/lazberrypi/). (noted dead link in late 2023)
11331127- Stefan Fischer's [rpi_hal library](https://github.com/rudiratlos/rpi-hal) and [rpi_hal discussion topic](http://www.lazarus.freepascal.org/index.php/topic,20991.0.html) on Lazarus forum.
11341128- [Improved Lazarus Unit for fast access to GPIO](http://www.meltonisl.com/pigpio.pas).
11351129- [PXL - Platform eXtended Library](http://asphyre.net/products/pxl).
11361130- [RPIIO - Raspberry Pi GPIO and I2C library](https://github.com/zipplet/rpiio).
11371131
11381132---
11391133*From the Free Pascal wiki, page "Lazarus on Raspberry Pi", as it stood on 2023-12-31 after a change by Dbannon, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history