Sign in Join
Wiki copytemporary

Lazarus on Raspberry Pi: what changed

Revision 3 to 4. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11![](/wiki-images/e/ef/Lazarus_on_Raspberry_Pi_Raspian_Wheezy_version_2012-10-28.png)
22
33*(Raspberry Pi only)*
44
55The **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.
66
77The 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]].
88
99Lazarus runs natively under the Raspbian operating system.
1010
1111## Installing and compiling Lazarus
1212
1313### Introduction
1414
1515Installing 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.
1616
1717- 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).
1818- The Lazarus SourceForge repository does not include a pre-made RasPi package.
1919- 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.
2020- 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 !
2121
2222### Correcting swap file size
2323
2424(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.
2525
2626To increase swap you should firstly ensure you have a couple of gig free and -
2727
2828- sudo dphys-swapfile swapoff
2929- sudo nano /etc/dphys-swapfile
3030- in the file, find CONF_SWAPSIZE and change the value to 2048 (or 1024) and save it.
3131- sudo dphys-swapfile setup
3232- sudo dphys-swapfile swapon
3333
3434You 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.
3535
3636If 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 !
3737
3838While 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.
3939
4040If you have problems making the swap file, see this <https://forums.raspberrypi.com/viewtopic.php?p=1881546>
4141
4242### Simple installation
4343
4444Most 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.
4545
4646A advantage of using the distro supplied FPC and Lazarus is that they test them, make sure everything needed is there and its very easy.
4747
4848See [the Package Manager Model](https://wiki.freepascal.org/Installing_Lazarus_on_Linux#The_Package_Manager_Model).
4949
5050### Not Quite as Simple Install
5151
5252There 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.
5353
5454Installing 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.
5555
5656Its quite reasonable to use the distro provided FPC and build your own Lazarus. In fact, many users have several lazarus versions installed this way.
5757
5858Building 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]].
5959
60-<File:Lazarus> 0 9 30 4 on RPi 2.png\|Lazarus "out of the box" on Raspberry Pi 2
60+![](/wiki-images/c/cc/Lazarus_0_9_30_4_on_RPi_2.png)
61+
62+Lazarus "out of the box" on Raspberry Pi 2
6163
6264### Cross compiling for the Raspberry Pi from Windows
6365
64661\. Using fpcup
6567
6668One way is to use fpcup to set up a cross compiler; follow these instructions: [[fpcup|fpcup#Linux_ARM_cross_compiler]]
6769
68702\. Using scripts
6971
7072Alternatively, for a more manual approach using batch files, you can follow these steps.
7173
72742.1 Prerequisites
7375
7476`FPC 2.7.1 or higher installed with source code`\
7577`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)
7678
77792.2 Example Windows Batch file (adapt paths as needed)
7880
7981``` bat
8082set PATH=C:\pp\bin\i386-win32;%PATH%;
8183set FPCMAKEPATH=C:/pp
8284set FPCPATH=C:/pp
8385set OUTPATH=C:/pp271
8486%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
8587
8688%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
8789if errorlevel 1 goto quit
8890%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%
8991
9092:quit
9193pause
9294```
9395
9496With 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.
9597
9698Remember that not all - especially Windows - libraries are available for Linux arm.
9799
98100### Cross compiling for the Raspberry Pi from Linux
99101
100102Please see this page <https://wiki.freepascal.org/Cross_Compile_to_RasPi_from_Linux>
101103
102104## Accessing external hardware
103105
104106![](/wiki-images/f/f2/Rpi_pinout_all_50.png)
105107
106108One 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:
107109
1081101. [[Lazarus on Raspberry Pi|Direct access]] using the [[BaseUnix]] unit
1091112. Access through [[Lazarus on Raspberry Pi|encapsulated shell calls]]
1101123. Access through the [[Lazarus on Raspberry Pi|wiringPi library]].
1111134. Access through Unit [[Lazarus on Raspberry Pi|rpi_hal]].
1121145. Access through Unit [[Lazarus on Raspberry Pi|PiGpio]].
1131156. Access through the [PascalIO](https://github.com/SAmeis/pascalio) library.
1141167. Access through the [PXL](http://asphyre.net/products/pxl) library.
115117
116118### Native hardware access
117119
118120![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.
119121
120122#### Switching a device via the GPIO port
121123
122124The 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*.
123125
124126For 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.
125127
126128The 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.
127129
128130``` bash
129131sudo adduser pi gpio
130132sudo adduser pi i2c
131133sudo adduser pi spi
132134```
133135
134136*Controlling unit:*
135137
136138``` pascal
137139unit Unit1;
138140
139141{Demo application for GPIO on Raspberry Pi}
140142{Inspired by the Python input/output demo application by Gareth Halfacree}
141143{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
142144
143145{$mode objfpc}{$H+}
144146
145147interface
146148
147149uses
148150 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
149151 Unix, BaseUnix;
150152
151153type
152154
153155 { TForm1 }
154156
155157 TForm1 = class(TForm)
156158 LogMemo: TMemo;
157159 GPIO17ToggleBox: TToggleBox;
158160 procedure FormActivate(Sender: TObject);
159161 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
160162 procedure GPIO17ToggleBoxChange(Sender: TObject);
161163 private
162164 { private declarations }
163165 public
164166 { public declarations }
165167 end;
166168
167169const
168170 PIN_17: PChar = '17';
169171 PIN_ON: PChar = '1';
170172 PIN_OFF: PChar = '0';
171173 OUT_DIRECTION: PChar = 'out';
172174
173175var
174176 Form1: TForm1;
175177 gReturnCode: longint; {stores the result of the IO operation}
176178
177179implementation
178180
179181{$R *.lfm}
180182
181183{ TForm1 }
182184
183185procedure TForm1.FormActivate(Sender: TObject);
184186var
185187 fileDesc: integer;
186188begin
187189 { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
188190 try
189191 fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
190192 gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
191193 LogMemo.Lines.Add(IntToStr(gReturnCode));
192194 finally
193195 gReturnCode := fpclose(fileDesc);
194196 LogMemo.Lines.Add(IntToStr(gReturnCode));
195197 end;
196198 { Set SoC pin 17 as output: }
197199 try
198200 fileDesc := fpopen('/sys/class/gpio/gpio17/direction', O_WrOnly);
199201 gReturnCode := fpwrite(fileDesc, OUT_DIRECTION[0], 3);
200202 LogMemo.Lines.Add(IntToStr(gReturnCode));
201203 finally
202204 gReturnCode := fpclose(fileDesc);
203205 LogMemo.Lines.Add(IntToStr(gReturnCode));
204206 end;
205207end;
206208
207209procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
208210var
209211 fileDesc: integer;
210212begin
211213 { Free SoC pin 17: }
212214 try
213215 fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
214216 gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
215217 LogMemo.Lines.Add(IntToStr(gReturnCode));
216218 finally
217219 gReturnCode := fpclose(fileDesc);
218220 LogMemo.Lines.Add(IntToStr(gReturnCode));
219221 end;
220222end;
221223
222224procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
223225var
224226 fileDesc: integer;
225227begin
226228 if GPIO17ToggleBox.Checked then
227229 begin
228230 { Swith SoC pin 17 on: }
229231 try
230232 fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
231233 gReturnCode := fpwrite(fileDesc, PIN_ON[0], 1);
232234 LogMemo.Lines.Add(IntToStr(gReturnCode));
233235 finally
234236 gReturnCode := fpclose(fileDesc);
235237 LogMemo.Lines.Add(IntToStr(gReturnCode));
236238 end;
237239 end
238240 else
239241 begin
240242 { Switch SoC pin 17 off: }
241243 try
242244 fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
243245 gReturnCode := fpwrite(fileDesc, PIN_OFF[0], 1);
244246 LogMemo.Lines.Add(IntToStr(gReturnCode));
245247 finally
246248 gReturnCode := fpclose(fileDesc);
247249 LogMemo.Lines.Add(IntToStr(gReturnCode));
248250 end;
249251 end;
250252end;
251253
252254end.
253255```
254256
255257*Main program:*
256258
257259``` pascal
258260program io_test;
259261
260262{$mode objfpc}{$H+}
261263
262264uses
263265 {$IFDEF UNIX}{$IFDEF UseCThreads}
264266 cthreads,
265267 {$ENDIF}{$ENDIF}
266268 Interfaces, // this includes the LCL widgetset
267269 Forms, Unit1
268270 { you can add units after this };
269271
270272{$R *.res}
271273
272274begin
273275 Application.Initialize;
274276 Application.CreateForm(TForm1, Form1);
275277 Application.Run;
276278end.
277279```
278280
279281#### Reading the status of a pin
280282
281283![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)
282284
283285Of course it is also possible to read the status of e.g. a switch that is connected to the GPIO port.
284286
285287The 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*.
286288
287289For 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.
288290
289291Note 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.
290292
291293This program has again to be executed as root.
292294
293295*Controlling unit:*
294296
295297``` pascal
296298unit Unit1;
297299
298300{Demo application for GPIO on Raspberry Pi}
299301{Inspired by the Python input/output demo application by Gareth Halfacree}
300302{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
301303
302304{This application reads the status of a push-button}
303305
304306{$mode objfpc}{$H+}
305307
306308interface
307309
308310uses
309311 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
310312 ButtonPanel, Unix, BaseUnix;
311313
312314type
313315
314316 { TForm1 }
315317
316318 TForm1 = class(TForm)
317319 ApplicationProperties1: TApplicationProperties;
318320 GPIO18CheckBox: TCheckBox;
319321 LogMemo: TMemo;
320322 procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
321323 procedure FormActivate(Sender: TObject);
322324 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
323325 private
324326 { private declarations }
325327 public
326328 { public declarations }
327329 end;
328330
329331const
330332 PIN_18: PChar = '18';
331333 IN_DIRECTION: PChar = 'in';
332334
333335var
334336 Form1: TForm1;
335337 gReturnCode: longint; {stores the result of the IO operation}
336338
337339implementation
338340
339341{$R *.lfm}
340342
341343{ TForm1 }
342344
343345procedure TForm1.FormActivate(Sender: TObject);
344346var
345347 fileDesc: integer;
346348begin
347349 { Prepare SoC pin 18 (pin 12 on GPIO port) for access: }
348350 try
349351 fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
350352 gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
351353 LogMemo.Lines.Add(IntToStr(gReturnCode));
352354 finally
353355 gReturnCode := fpclose(fileDesc);
354356 LogMemo.Lines.Add(IntToStr(gReturnCode));
355357 end;
356358 { Set SoC pin 18 as input: }
357359 try
358360 fileDesc := fpopen('/sys/class/gpio/gpio18/direction', O_WrOnly);
359361 gReturnCode := fpwrite(fileDesc, IN_DIRECTION[0], 2);
360362 LogMemo.Lines.Add(IntToStr(gReturnCode));
361363 finally
362364 gReturnCode := fpclose(fileDesc);
363365 LogMemo.Lines.Add(IntToStr(gReturnCode));
364366 end;
365367end;
366368
367369procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
368370var
369371 fileDesc: integer;
370372 buttonStatus: string[1] = '1';
371373begin
372374 try
373375 { Open SoC pin 18 (pin 12 on GPIO port) in read-only mode: }
374376 fileDesc := fpopen('/sys/class/gpio/gpio18/value', O_RdOnly);
375377 if fileDesc > 0 then
376378 begin
377379 { Read status of this pin (0: button pressed, 1: button released): }
378380 gReturnCode := fpread(fileDesc, buttonStatus[1], 1);
379381 LogMemo.Lines.Add(IntToStr(gReturnCode) + ': ' + buttonStatus);
380382 LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
381383 if buttonStatus = '0' then
382384 GPIO18CheckBox.Checked := true
383385 else
384386 GPIO18CheckBox.Checked := false;
385387 end;
386388 finally
387389 { Close SoC pin 18 (pin 12 on GPIO port) }
388390 gReturnCode := fpclose(fileDesc);
389391 LogMemo.Lines.Add(IntToStr(gReturnCode));
390392 LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
391393 end;
392394end;
393395
394396procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
395397var
396398 fileDesc: integer;
397399begin
398400 { Free SoC pin 18: }
399401 try
400402 fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
401403 gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
402404 LogMemo.Lines.Add(IntToStr(gReturnCode));
403405 finally
404406 gReturnCode := fpclose(fileDesc);
405407 LogMemo.Lines.Add(IntToStr(gReturnCode));
406408 end;
407409end;
408410
409411end.
410412```
411413
412414The main program is identical to that of the example from above.
413415
414416### Hardware access via encapsulated shell calls
415417
416418Another 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.
417419
418420*Controlling unit:*
419421
420422``` pascal
421423unit Unit1;
422424
423425{Demo application for GPIO on Raspberry Pi}
424426{Inspired by the Python input/output demo application by Gareth Halfacree}
425427{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
426428
427429{$mode objfpc}{$H+}
428430
429431interface
430432
431433uses
432434 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Unix;
433435
434436type
435437
436438 { TForm1 }
437439
438440 TForm1 = class(TForm)
439441 LogMemo: TMemo;
440442 GPIO17ToggleBox: TToggleBox;
441443 procedure FormActivate(Sender: TObject);
442444 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
443445 procedure GPIO17ToggleBoxChange(Sender: TObject);
444446 private
445447 { private declarations }
446448 public
447449 { public declarations }
448450 end;
449451
450452var
451453 Form1: TForm1;
452454 gReturnCode: longint; {stores the result of the IO operation}
453455
454456implementation
455457
456458{$R *.lfm}
457459
458460{ TForm1 }
459461
460462procedure TForm1.FormActivate(Sender: TObject);
461463begin
462464 { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
463465 gReturnCode := fpsystem('echo "17" > /sys/class/gpio/export');
464466 LogMemo.Lines.Add(IntToStr(gReturnCode));
465467 { Set SoC pin 17 as output: }
466468 gReturnCode := fpsystem('echo "out" > /sys/class/gpio/gpio17/direction');
467469 LogMemo.Lines.Add(IntToStr(gReturnCode));
468470end;
469471
470472procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
471473begin
472474 { Free SoC pin 17: }
473475 gReturnCode := fpsystem('echo "17" > /sys/class/gpio/unexport');
474476 LogMemo.Lines.Add(IntToStr(gReturnCode));
475477end;
476478
477479procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
478480begin
479481 if GPIO17ToggleBox.Checked then
480482 begin
481483 { Swith SoC pin 17 on: }
482484 gReturnCode := fpsystem('echo "1" > /sys/class/gpio/gpio17/value');
483485 LogMemo.Lines.Add(IntToStr(gReturnCode));
484486 end
485487 else
486488 begin
487489 { Switch SoC pin 17 off: }
488490 gReturnCode := fpsystem('echo "0" > /sys/class/gpio/gpio17/value');
489491 LogMemo.Lines.Add(IntToStr(gReturnCode));
490492 end;
491493end;
492494
493495end.
494496```
495497
496498The main program is identical to that of the example above. This program has to be executed with root privileges, too.
497499
498500### wiringPi procedures and functions
499501
500502Alex Schaller's wrapper unit for Gordon Henderson's Arduino compatible wiringPi library provides a numbering scheme that resembles that of Arduino boards.
501503
502504**Function wiringPiSetup:longint:** Initializes wiringPi system using the wiringPi pin numbering scheme.
503505
504506**Procedure wiringPiGpioMode(mode:longint):** Initializes wiringPi system with the Broadcom GPIO pin numbering scheme.
505507
506508**Procedure pullUpDnControl(pin:longint;** pud:longint): controls the internal pull-up/down resistors on a GPIO pin.
507509
508510**Procedure pinMode(pin:longint; mode:longint):** sets the mode of a pin to either INPUT, OUTPUT, or PWM_OUTPUT.
509511
510512**Procedure digitalWrite(pin:longint; value:longint):** sets an output bit.
511513
512514**Procedure pwmWrite(pin:longint; value:longint):** sets an output PWM value between 0 and 1024.
513515
514516**Function digitalRead(pin:longint):longint:** reads the value of a given Pin, returning 1 or 0.
515517
516518**Procedure delay(howLong:dword):** waits for at least howLong milliseconds.
517519
518520**Procedure delayMicroseconds(howLong:dword):** waits for at least howLong microseconds.
519521
520522**Function millis:dword:** returns the number of milliseconds since the program called one of the wiringPiSetup functions.
521523
522524### rpi_hal-Hardware Abstraction Library (GPIO, I2C and SPI functions and procedures)
523525
524526This Unit with around 1700 Lines of Code provided by Stefan Fischer, delivers procedures and functions to access the rpi HW I2C, SPI and GPIO:
525527
526528Just an excerpt of the available functions and procedures:
527529
528530**procedure gpio_set_pin (pin:longword;highlevel:boolean);** { Set RPi GPIO pin to high or low level; Speed @ 700MHz -\> 0.65MHz }
529531
530532**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 }
531533
532534**procedure gpio_set_input (pin:longword);** { Set RPi GPIO pin to input direction }
533535
534536**procedure gpio_set_output(pin:longword);** { Set RPi GPIO pin to output direction }
535537
536538**procedure gpio_set_alt (pin,altfunc:longword);** { Set RPi GPIO pin to alternate function nr. 0..5 }
537539
538540**procedure gpio_set_gppud (mask:longword);** { set RPi GPIO Pull-up/down Register (GPPUD) with mask }
539541
540542...
541543
542544**function rpi_snr :string;** { delivers SNR: 0000000012345678 }
543545
544546**function rpi_hw :string;** { delivers Processor Type: BCM2708 }
545547
546548**function rpi_proc:string;** { ARMv6-compatible processor rev 7 (v6l) }
547549
548550...
549551
550552**function i2c_bus_write(baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : integer;**
551553
552554**function i2c_bus_read (baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : integer;**
553555
554556**function i2c_string_read(baseadr,reg:word; var <data:databuf_t>; lgt:byte; testnr:integer) : string;**
555557
556558**function i2c_string_write(baseadr,reg:word; s:string; testnr:integer) : integer;**
557559
558560...
559561
560562**procedure SPI_Write(devnum:byte; reg,data:word);**
561563
562564**function SPI_Read(devnum:byte; reg:word) : byte;**
563565
564566**procedure SPI_BurstRead2Buffer (devnum,start_reg:byte; xferlen:longword);**
565567
566568**procedure SPI_BurstWriteBuffer (devnum,start_reg:byte; xferlen:longword);** { Write 'len' Bytes from Buffer SPI Dev startig at address 'reg' }
567569
568570...
569571
570572*Test Program (testrpi.pas):*
571573
572574``` pascal
573575//Simple Test program, which is using rpi_hal;
574576
575577 program testrpi;
576578 uses rpi_hal;
577579 begin
578580 writeln('Show CPU-Info, RPI-HW-Info and Registers:');
579581 rpi_show_all_info;
580582 writeln('Let Status LED Blink. Using GPIO functions:');
581583 GPIO_PIN_TOGGLE_TEST;
582584 writeln('Test SPI Read function. (piggy back board with installed RFM22B Module is required!)');
583585 Test_SPI;
584586 end.
585587```
586588
587589### PiGpio Low-level native pascal unit (GPIO control instead of wiringPi c library)
588590
589591*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) :*
590592
591593``` pascal
592594
593595unit PiGpio;
594596{
595597 BCM2835 GPIO Registry Driver, also can use to manipulate cpu other registry areas
596598
597599 This code is tested only Broadcom bcm2835 cpu, different arm cpus may need different
598600 gpio driver implementation
599601
600602 2013 Gabor Szollosi
601603}
602604{$mode objfpc}{$H+}
603605
604606interface
605607
606608uses
607609 Classes, SysUtils;
608610
609611const
610612 REG_GPIO = $3F000;// bcm2835 gpio register 0x2000 0000 (RPi1), 0x3F00 0000 (RPi2)
611613 // new fpMap uses page offset, one page is 4096 bytes = 0x1000 so simply calculate 0x2000 0000 / 0x1000 = 0x2000 0
612614 PAGE_SIZE = 4096;
613615 BLOCK_SIZE = 4096;
614616 // The BCM2835 has 54 GPIO pins.
615617 // BCM2835 data sheet, Page 90 onwards.
616618 // There are 6 control registers, each control the functions of a block
617619 // of 10 pins.
618620
619621 CLOCK_BASE = (REG_GPIO + $101);
620622 GPIO_BASE = (REG_GPIO + $200);
621623 GPIO_PWM = (REG_GPIO + $20C);
622624
623625 INPUT = 0;
624626 OUTPUT = 1;
625627 PWM_OUTPUT = 2;
626628 LOW = False;
627629 HIGH = True;
628630 PUD_OFF = 0;
629631 PUD_DOWN = 1;
630632 PUD_UP = 2;
631633
632634 // PWM
633635
634636 PWM_CONTROL = 0;
635637 PWM_STATUS = 4;
636638 PWM0_RANGE = 16;
637639 PWM0_DATA = 20;
638640 PWM1_RANGE = 32;
639641 PWM1_DATA = 36;
640642
641643 PWMCLK_CNTL = 160;
642644 PWMCLK_DIV = 164;
643645
644646 PWM1_MS_MODE = $8000; // Run in MS mode
645647 PWM1_USEFIFO = $2000; // Data from FIFO
646648 PWM1_REVPOLAR = $1000; // Reverse polarity
647649 PWM1_OFFSTATE = $0800; // Ouput Off state
648650 PWM1_REPEATFF = $0400; // Repeat last value if FIFO empty
649651 PWM1_SERIAL = $0200; // Run in serial mode
650652 PWM1_ENABLE = $0100; // Channel Enable
651653
652654 PWM0_MS_MODE = $0080; // Run in MS mode
653655 PWM0_USEFIFO = $0020; // Data from FIFO
654656 PWM0_REVPOLAR = $0010; // Reverse polarity
655657 PWM0_OFFSTATE = $0008; // Ouput Off state
656658 PWM0_REPEATFF = $0004; // Repeat last value if FIFO empty
657659 PWM0_SERIAL = $0002; // Run in serial mode
658660 PWM0_ENABLE = $0001; // Channel Enable
659661
660662type
661663
662664 { TIoPort }
663665
664666 TIoPort = class // IO bank object
665667 private //
666668
667669 //function get_pinDirection(aPin: TGpIoPin): TGpioPinConf;
668670
669671 public
670672 FGpio: ^LongWord;
671673 FClk: ^LongWord;
672674 FPwm: ^LongWord;
673675 procedure SetPinMode(gpin, mode: byte);
674676 function GetBit(gpin : byte):boolean;inline; // gets pin bit}
675677 procedure ClearBit(gpin : byte);inline;// write pin to 0
676678 procedure SetBit(gpin : byte);inline;// write pin to 1
677679 procedure SetPullMode(gpin, mode: byte);
678680 procedure PwmWrite(gpin : byte; value : LongWord);inline;// write pin to pwm value
679681 end;
680682
681683 { TIoDriver }
682684
683685 TIoDriver = class
684686 private
685687
686688 public
687689 destructor Destroy;override;
688690 function MapIo:boolean;// creates io memory mapping
689691 procedure UnmapIoRegisrty(FMap: TIoPort);// close io memory mapping
690692 function CreatePort(PortGpio, PortClk, PortPwm: LongWord):TIoPort; // create new IO port
691693 end;
692694
693695var
694696
695697 fd: integer;// /dev/mem file handle
696698procedure delayNanoseconds (howLong : LongWord);
697699
698700implementation
699701
700702uses
701703 baseUnix, Unix;
702704
703705procedure delayNanoseconds (howLong : LongWord);
704706var
705707 sleeper, dummy : timespec;
706708begin
707709 sleeper.tv_sec := 0 ;
708710 sleeper.tv_nsec := howLong ;
709711 fpnanosleep (@sleeper,@dummy) ;
710712end;
711713{ TIoDriver }
712714//*******************************************************************************
713715destructor TIoDriver.Destroy;
714716begin
715717 inherited Destroy;
716718end;
717719//*******************************************************************************
718720function TIoDriver.MapIo: boolean;
719721begin
720722 Result := True;
721723 fd := fpopen('/dev/mem', O_RdWr or O_Sync); // Open the master /dev/memory device
722724 if fd < 0 then
723725 begin
724726 Result := False; // unsuccessful memory mapping
725727 end;
726728 //
727729end;
728730//*******************************************************************************
729731procedure TIoDriver.UnmapIoRegisrty(FMap:TIoPort);
730732begin
731733 if FMap.FGpio <> nil then
732734 begin
733735 fpMUnmap(FMap.FGpio,PAGE_SIZE);
734736 FMap.FGpio := Nil;
735737 end;
736738 if FMap.FClk <> nil then
737739 begin
738740 fpMUnmap(FMap.FClk,PAGE_SIZE);
739741 FMap.FClk := Nil;
740742 end;
741743 if FMap.FPwm <> nil then
742744 begin
743745 fpMUnmap(FMap.FPwm ,PAGE_SIZE);
744746 FMap.FPwm := Nil;
745747 end;
746748end;
747749//*******************************************************************************
748750function TIoDriver.CreatePort(PortGpio, PortClk, PortPwm: LongWord): TIoPort;
749751begin
750752 Result := TIoPort.Create;// new io port, pascal calls new fpMap, where offst is page sized 4096 bytes!!!
751753 Result.FGpio := FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortGpio); // port config gpio memory
752754 Result.FClk:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortClk);; // port clk
753755 Result.FPwm:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortPwm);; // port pwm
754756end;
755757//*******************************************************************************
756758procedure TIoPort.SetPinMode(gpin, mode: byte);
757759var
758760 fSel, shift, alt : byte;
759761 gpiof, clkf, pwmf : ^LongWord;
760762begin
761763 fSel := (gpin div 10)*4 ; //Select Gpfsel 0 to 5 register
762764 shift := (gpin mod 10)*3 ; //0-9 pin shift
763765 gpiof := Pointer(LongWord(Self.FGpio)+fSel);
764766 if (mode = INPUT) then
765767 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) //7 shl shift komplemens - Sets bits to zero = input
766768 else if (mode = OUTPUT) then
767769 begin
768770 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (1 shl shift);
769771 end
770772 else if (mode = PWM_OUTPUT) then
771773 begin
772774 Case gpin of
773775 12,13,40,41,45 : alt:= 4 ;
774776 18,19 : alt:= 2 ;
775777 else alt:= 0 ;
776778 end;
777779 If alt > 0 then
778780 begin
779781 gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (alt shl shift);
780782 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
781783 clkf^ := $5A000011 or (1 shl 5) ; //stop clock
782784 delayNanoseconds(200);
783785 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_DIV);
784786 clkf^ := $5A000000 or (32 shl 12) ; // set pwm clock div to 32 (19.2/3 = 600KHz)
785787 clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
786788 clkf^ := $5A000011 ; //start clock
787789 Self.ClearBit(gpin);
788790 pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
789791 pwmf^ := 0 ; // Disable PWM
790792 delayNanoseconds(200);
791793 pwmf := Pointer(LongWord(Self.FPwm)+PWM0_RANGE);
792794 pwmf^ := $400 ; //max: 1023
793795 delayNanoseconds(200);
794796 pwmf := Pointer(LongWord(Self.FPwm)+PWM1_RANGE);
795797 pwmf^ := $400 ; //max: 1023
796798 delayNanoseconds(200);
797799 // Enable PWMs
798800 pwmf := Pointer(LongWord(Self.FPwm)+PWM0_DATA);
799801 pwmf^ := 0 ; //start value
800802 pwmf := Pointer(LongWord(Self.FPwm)+PWM1_DATA);
801803 pwmf^ := 0 ; //start value
802804 pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
803805 pwmf^ := PWM0_ENABLE or PWM1_ENABLE ;
804806 end;
805807 end;
806808end;
807809//*******************************************************************************
808810procedure TIoPort.SetBit(gpin : byte);
809811var
810812 gpiof : ^LongWord;
811813begin
812814 gpiof := Pointer(LongWord(Self.FGpio) + 28 + (gpin shr 5) shl 2);
813815 gpiof^ := 1 shl gpin;
814816end;
815817//*******************************************************************************
816818procedure TIoPort.ClearBit(gpin : byte);
817819var
818820 gpiof : ^LongWord;
819821begin
820822 gpiof := Pointer(LongWord(Self.FGpio) + 40 + (gpin shr 5) shl 2);
821823 gpiof^ := 1 shl gpin;
822824end;
823825//*******************************************************************************
824826function TIoPort.GetBit(gpin : byte):boolean;
825827var
826828 gpiof : ^LongWord;
827829begin
828830 gpiof := Pointer(LongWord(Self.FGpio) + 52 + (gpin shr 5) shl 2);
829831 if (gpiof^ and (1 shl gpin)) = 0 then Result := False else Result := True;
830832end;
831833//*******************************************************************************
832834procedure TIoPort.SetPullMode(gpin, mode: byte);
833835var
834836 pudf, pudclkf : ^LongWord;
835837begin
836838 pudf := Pointer(LongWord(Self.FGpio) + 148 );
837839 pudf^ := mode; //mode = 0, 1, 2 :Off, Down, Up
838840 delayNanoseconds(200);
839841 pudclkf := Pointer(LongWord(Self.FGpio) + 152 + (gpin shr 5) shl 2);
840842 pudclkf^ := 1 shl gpin ;
841843 delayNanoseconds(200);
842844 pudf^ := 0 ;
843845 pudclkf^ := 0 ;
844846end;
845847//*******************************************************************************
846848procedure TIoPort.PwmWrite(gpin : byte; value : Longword);
847849var
848850 pwmf : ^LongWord;
849851 port : byte;
850852begin
851853 Case gpin of
852854 12,18,40 : port:= PWM0_DATA ;
853855 13,19,41,45 : port:= PWM1_DATA ;
854856 else exit;
855857 end;
856858 pwmf := Pointer(LongWord(Self.FPwm) + port);
857859 pwmf^ := value and $FFFFFBFF; // $400 complemens
858860end;
859861//*******************************************************************************
860862end.
861863```
862864
863865*Controlling Lazarus unit:(Project files[3](https://drive.google.com/folderview?id=0B-b-5ooIWPvGU043ZTZ0cUc2YkE&usp=sharing))*
864866
865867``` pascal
866868unit Unit1;
867869
868870{Demo application for GPIO on Raspberry Pi}
869871{Inspired by the Python input/output demo application by Gareth Halfacree}
870872{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
871873
872874{$mode objfpc}{$H+}
873875
874876interface
875877
876878uses
877879 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
878880 ExtCtrls, Unix, PiGpio;
879881
880882type
881883
882884 { TForm1 }
883885
884886 TForm1 = class(TForm)
885887 GPIO25In: TButton;
886888 SpeedButton: TButton;
887889 LogMemo: TMemo;
888890 GPIO23switch: TToggleBox;
889891 Timer1: TTimer;
890892 GPIO18Pwm: TToggleBox;
891893 Direction: TToggleBox;
892894 procedure DirectionChange(Sender: TObject);
893895 procedure GPIO18PwmChange(Sender: TObject);
894896 procedure GPIO25InClick(Sender: TObject);
895897 procedure FormActivate(Sender: TObject);
896898 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
897899 procedure GPIO23switchChange(Sender: TObject);
898900 procedure SpeedButtonClick(Sender: TObject);
899901 procedure Timer1Timer(Sender: TObject);
900902 private
901903 { private declarations }
902904 public
903905 { public declarations }
904906 end;
905907
906908const
907909 INPUT = 0;
908910 OUTPUT = 1;
909911 PWM_OUTPUT = 2;
910912 LOW = False;
911913 HIGH = True;
912914 PUD_OFF = 0;
913915 PUD_DOWN = 1;
914916 PUD_UP = 2;
915917 // Convert Raspberry Pi P1 pins (Px) to GPIO port
916918 P3 = 0;
917919 P5 = 1;
918920 P7 = 4;
919921 P8 = 14;
920922 P10 = 15;
921923 P11 = 17;
922924 P12 = 18;
923925 P13 = 21;
924926 P15 = 22;
925927 P16 = 23;
926928 P18 = 24;
927929 P19 = 10;
928930 P21 = 9;
929931 P22 = 25;
930932 P23 = 11;
931933 P24 = 8;
932934 P26 = 7;
933935
934936var
935937 Form1: TForm1;
936938 GPIO_Driver: TIoDriver;
937939 GpF: TIoPort;
938940 PWM :Boolean;
939941 i, d : integer;
940942 Pin,Pout,Ppwm : byte;
941943
942944implementation
943945
944946{$R *.lfm}
945947
946948{ TForm1 }
947949
948950procedure TForm1.FormActivate(Sender: TObject);
949951begin
950952 if not GPIO_Driver.MapIo then
951953 begin
952954 LogMemo.Lines.Add('Error mapping gpio registry');
953955 end
954956 else
955957 begin
956958 GpF := GpIo_Driver.CreatePort(GPIO_BASE, CLOCK_BASE, GPIO_PWM);
957959 end ;
958960 Timer1.Enabled:= True;
959961 Timer1.Interval:= 25; //25 ms controll interval
960962 Pin := P22;
961963 Pout := P16;
962964 Ppwm := P12;
963965 i:=1;
964966 GpF.SetPinMode(Pout,OUTPUT);
965967 GpF.SetPinMode(Pin,INPUT);
966968 GpF.SetPullMode(Pin,PUD_Up); // Input PullUp High level
967969end;
968970
969971procedure TForm1.GPIO25InClick(Sender: TObject);
970972begin
971973 If GpF.GetBit(Pin) then LogMemo.Lines.Add('In: '+IntToStr(1))
972974 else LogMemo.Lines.Add('In: '+IntToStr(0));
973975end;
974976
975977procedure TForm1.GPIO18PwmChange(Sender: TObject);
976978begin
977979 if GPIO18Pwm.Checked then
978980 begin
979981 GpF.SetPinMode(Ppwm,PWM_OUTPUT);
980982 PWM := True; //PWM on
981983 end
982984 else
983985 begin
984986 GpF.SetPinMode(Ppwm,INPUT);
985987 PWM := False; //PWM off
986988 end;
987989end;
988990
989991procedure TForm1.DirectionChange(Sender: TObject);
990992begin
991993 if Direction.Checked then d:=10 else d:=-10;
992994end;
993995
994996
995997procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
996998begin
997999 GpF.SetPinMode(Ppwm,INPUT);
9981000 GpF.ClearBit(Pout);
9991001 GpIo_Driver.UnmapIoRegisrty(GpF);
10001002end;
10011003
10021004procedure TForm1.GPIO23switchChange(Sender: TObject);
10031005
10041006Begin
10051007 Timer1.Enabled := False;
10061008 if GPIO23switch.Checked then
10071009 begin
10081010 GpF.SetBit(Pout); //Turn LED on
10091011 end
10101012 else
10111013 begin
10121014 GpF.ClearBit(Pout); //Turn LED off
10131015 end;
10141016 Timer1.Enabled := True;
10151017end;
10161018
10171019procedure TForm1.SpeedButtonClick(Sender: TObject);
10181020var
10191021 i,p,k,v: longint;
10201022 ido:TDateTime;
10211023begin
10221024 ido:= Time;
10231025 k:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
10241026 LogMemo.Lines.Add('Start: '+TimeToStr(ido));
10251027 p:=10000000 ;
10261028 For i:=1 to p do Begin
10271029 GpF.SetBit(P16);
10281030 GpF.ClearBit(P16);
10291031 end;
10301032 ido:= Time;
10311033 v:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
10321034 LogMemo.Lines.Add('Stop: '+TimeToStr(ido)+' Frequency: '+
10331035 IntToStr(p div (v-k))+' kHz');
10341036end;
10351037
10361038procedure TForm1.Timer1Timer(Sender: TObject);
10371039begin
10381040 If PWM then Begin
10391041 If (d > 0) and (i+d < 1024) then begin
10401042 i:=i+d;
10411043 GpF.PwmWrite(Ppwm,i);
10421044 end ;
10431045 If (d < 0) and (i+d > -1) then begin
10441046 i:=i+d;
10451047 GpF.PwmWrite(Ppwm,i);
10461048 end;
10471049 end;
10481050end;
10491051
10501052
10511053end.
10521054```
10531055
10541056### PXL (Platform eXtended Library) for low level native access to GPIO, I²C, SPI, PWM, UART, V4L2, displays and sensors
10551057
10561058- Easy and fast access to GPIO, I²C, SPI, PWM, UART and high precision CPU timer.
10571059- V4L2 video/image capture using onboard and USB cameras. Serial cameras such as VC0706 and LSY201.
10581060- OpenGL ES hardware rendering with and without X server. Software rendering.
10591061- I²C and SPI displays such as SSD1306, SSD1351, PCB8544 (Nokia), HX8357 and ILI9340.
10601062- Character LCDs with direct pin wiring.
10611063- Support for Software SPI and UART (bit-banging).
10621064- Support for SC16IS7x0 (UART controller connected via I²C or SPI), including extra GPIO pins.
10631065- Support for sensors such as BMP180, DHT22, L3GD20, LSM303 and SHT10.
10641066- Other features like networking, math, image transformation, effects, drawing primitives...
10651067
10661068*More info and download of [PXL library](http://asphyre.net/products/pxl).*
10671069
10681070*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.*
10691071
10701072``` pascal
10711073
10721074procedure TFastGPIO.SetPinDrive(const Pin: TPinIdentifier; const Value: TPinDrive);
10731075const
10741076 GPPUDadr = $94;
10751077 GPPclkadr = $98;
10761078type
10771079 TBCM28PinDrive = (drvNone, drvPullDown, drvPullUp);
10781080var
10791081 dValue: TBCM28PinDrive;
10801082 PinBCM: TPinIdentifier;
10811083 GPPUD, GPPclk: Pointer;
10821084begin
10831085 case Value of
10841086 TPinDrive.PullUp: dValue := TBCM28PinDrive.drvPullDown;
10851087 TPinDrive.PullDown: dValue := TBCM28PinDrive.drvPullUp;
10861088 else
10871089 dValue := TBCM28PinDrive.drvNone;
10881090
10891091 PinBCM := ProcessPinNumber(Pin);
10901092
10911093 GPPUD := GetOffsetPointer(GPPUDadr);
10921094 WriteMemSafe(GPPUD, Cardinal(dValue));
10931095 FSystemCore.MicroDelay(1);
10941096
10951097 GPPclk := GetOffsetPointer(GPPclkadr + (Cardinal(PinBCM) div 32) * 4);
10961098 WriteMemSafe(GPPclk, 1 shl (PinBCM mod 32));
10971099 FSystemCore.MicroDelay(1);
10981100
10991101 WriteMemSafe(GPPUD, 0);
11001102 WriteMemSafe(GPPclk, 0);
11011103end;
11021104```
11031105
11041106## References
11051107
11061108- Eben Upton and Gareth Halfacree. Raspberry Pi User Guide. John Wiley and Sons, Chichester 2012, ISBN 111846446X
11071109- B. J. Rao (2013) The Raspberry Pi, Pi Vision and Lazarus/FPC. [Blaise Pascal Magazine](http://www.blaisepascal.eu). 29: 14-21.
11081110
11091111## External and Other Links
11101112
11111113- 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.
11121114
11131115It was written using gentoo but this guide will be useful with any distro: [[Install fpc on Raspberry with Gentoo]] (very out of date)
11141116
11151117- [Raspberry Pi Foundation](http://www.raspberrypi.org)
11161118- [Raspberry Pi Spy: Raspberry Pi tutorials, scripts, help and downloads](http://www.raspberrypi-spy.co.uk)
11171119- [Lazarus wrapper unit for Gordon Henderson's wiringPi C library](http://www.lazarus.freepascal.org/index.php/topic,17404.0.html)
11181120- [Another wiringPi wrapper with waitForInterrupt() and wiringPiISR()](https://github.com/laz2wiringpi/laz2wiringpi)
11191121- [Yet another wiringPi wrapper with waitForInterrupt(), wiringPiISR(), i2c, spi and serial](https://forum.lazarus.freepascal.org/index.php/topic,17404.msg405237.html#msg405237)
11201122- [Pin layout of the wiringPi library](https://projects.drogon.net/raspberry-pi/wiringpi/pins/)
11211123- [wiringPi fork updated for latest hardware](https://github.com/WiringPi/WiringPi)
11221124- [Additional information on Lazarus and Raspberry Pi at eLinux.org](http://www.elinux.org/Lazarus_on_RPi)
11231125- [Getting Started with Pascal on the Pi](http://www.pp4s.co.uk/main/gs-pi-intro.html) (noted dead link in late 2023)
11241126- [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)
11251127- [lazi2cdev - General i2c with drivers for ADS1015 ADC, MCP23017 IO, MCP4725 DAC, PCA9685 PWM and HD44780 LCD](https://github.com/laz2wiringpi/lazI2cdev)
11261128- [Lazberry Pi: Comprehensive information on Lazarus on the Raspberry Pi computer](http://superbitysoft.co.uk/lazberrypi/). (noted dead link in late 2023)
11271129- 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.
11281130- [Improved Lazarus Unit for fast access to GPIO](http://www.meltonisl.com/pigpio.pas).
11291131- [PXL - Platform eXtended Library](http://asphyre.net/products/pxl).
11301132- [RPIIO - Raspberry Pi GPIO and I2C library](https://github.com/zipplet/rpiio).
11311133
11321134---
11331135*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