• R/O
  • SSH
  • HTTPS

pasripherals: コミット


コミットメタ情報

リビジョン46 (tree)
日時2021-01-19 04:29:50
作者derekwildstar

ログメッセージ

Unit UBCMHost.pas criada e adicionada ao projeto. Esta unit deveria pertencer a alguma biblioteca geral, pois ela fornece funções que são usadas em PasRipherals, mas que são genéricas. Quem sabe um dia eu não crie um Krakatoa para o Pi?
Funções para obtenção de informaçes do RPI adicionadas
A função PeripheralsBaseAddressAndSize foi alterada para usar as funçes exportadas por UBCMHost, que são mais simples e eficientes
A função GetInfo foi atualizada para retornar informações referentes ao PI

変更サマリ

差分

--- trunk/src/lib/UBCMHost.pas (nonexistent)
+++ trunk/src/lib/UBCMHost.pas (revision 46)
@@ -0,0 +1,82 @@
1+unit UBCMHost;
2+{:< Esta unit é a tradução literal do cabeçalho bcm_host.h, que contém funções
3+úteis para obtenção de informações sobre o RPI. Para que esta unit seja
4+compilada, inclua no library path (-Fl) do projeto o caminho onde libbcm_host.so
5+está /opt/vc/lib (pasta de bibliotecas do firmware do RPI). Cuidado ao usar as
6+funçes desta biblioteca, pois aparentemente algumas delas ainda no consideram o
7+Pi4, por exemplo, bcm_host_get_processor_id retorna BCM_HOST_PROCESSOR_BCM2838
8+no Pi4, porém este Pi tem um BCM2711 de acordo com cat/cpuinfo. Realmente não
9+sei se está certo ou não, pois o Pi3 anterior tinha um BCM2835, logo, como o Pi4
10+tem um BCM2711 }
11+{$mode objfpc}{$H+}
12+
13+interface
14+
15+procedure bcm_host_init; cdecl;
16+procedure bcm_host_deinit; cdecl;
17+function graphics_get_display_size(const display_number: UINT16; width: PUINT32; height: PUINT32): INT32; cdecl;
18+function bcm_host_get_peripheral_address: UINT32; cdecl;
19+function bcm_host_get_peripheral_size: UINT32; cdecl;
20+function bcm_host_get_sdram_address: UINT32; cdecl;
21+
22+{: Retorna o tipo de Pi sendo usado }
23+function bcm_host_get_model_type: INT32; cdecl;
24+
25+const
26+ BCM_HOST_BOARD_TYPE_MODELA = 0;
27+ BCM_HOST_BOARD_TYPE_MODELB = 1;
28+ BCM_HOST_BOARD_TYPE_MODELAPLUS = 2;
29+ BCM_HOST_BOARD_TYPE_MODELBPLUS = 3;
30+ BCM_HOST_BOARD_TYPE_PI2MODELB = 4;
31+ BCM_HOST_BOARD_TYPE_ALPHA = 5;
32+ BCM_HOST_BOARD_TYPE_CM = 6;
33+ BCM_HOST_BOARD_TYPE_CM2 = 7;
34+ BCM_HOST_BOARD_TYPE_PI3MODELB = 8;
35+ BCM_HOST_BOARD_TYPE_PI0 = 9;
36+ BCM_HOST_BOARD_TYPE_CM3 = $0A;
37+ BCM_HOST_BOARD_TYPE_CUSTOM = $0B;
38+ BCM_HOST_BOARD_TYPE_PI0W = $0C;
39+ BCM_HOST_BOARD_TYPE_PI3MODELBPLUS = $0D;
40+ BCM_HOST_BOARD_TYPE_PI3MODELAPLUS = $0E;
41+ BCM_HOST_BOARD_TYPE_FPGA = $0F;
42+ BCM_HOST_BOARD_TYPE_CM3PLUS = $10;
43+ BCM_HOST_BOARD_TYPE_PI4MODELB = $11;
44+
45+{: Retorna True se é um Pi4 }
46+function bcm_host_is_model_pi4: Boolean; cdecl;
47+
48+{: Retorna True se fkms estiver ativo (dtoverlay=v3d-fkms-vc4) }
49+function bcm_host_is_fkms_active: Boolean; cdecl;
50+
51+{: Retorna True se kms estiver ativo (dtoverlay=v3d-kms-vc4) }
52+function bcm_host_is_kms_active: Boolean; cdecl;
53+
54+{: Retorna o ID do processador }
55+function bcm_host_get_processor_id: INT32; cdecl;
56+
57+const
58+ BCM_HOST_PROCESSOR_BCM2835 = 0;
59+ BCM_HOST_PROCESSOR_BCM2836 = 1;
60+ BCM_HOST_PROCESSOR_BCM2837 = 2;
61+ BCM_HOST_PROCESSOR_BCM2838 = 3;
62+
63+implementation
64+
65+const
66+ BCMHost = 'bcm_host';
67+
68+procedure bcm_host_init; cdecl; external BCMHost;
69+procedure bcm_host_deinit; cdecl; external BCMHost;
70+function graphics_get_display_size(const display_number: UINT16; width: PUINT32; height: PUINT32): INT32; cdecl; external BCMHost;
71+function bcm_host_get_peripheral_address: UINT32; cdecl; external BCMHost;
72+function bcm_host_get_peripheral_size: UINT32; cdecl; external BCMHost;
73+function bcm_host_get_sdram_address: UINT32; cdecl; external BCMHost;
74+
75+function bcm_host_get_model_type: INT32; cdecl; external;
76+function bcm_host_is_model_pi4: Boolean; cdecl; external;
77+function bcm_host_is_fkms_active: Boolean; cdecl; external;
78+function bcm_host_is_kms_active: Boolean; cdecl; external;
79+function bcm_host_get_processor_id: INT32; cdecl; external;
80+
81+end.
82+
--- trunk/src/lib/UPasRipherals.pas (revision 45)
+++ trunk/src/lib/UPasRipherals.pas (revision 46)
@@ -5,6 +5,11 @@
55
66 interface
77
8+{
9+* Referências úteis (inclua na ajuda no futuro)
10+* https://www.iot-programmer.com/index.php/books/22-raspberry-pi-and-the-iot-in-c/chapters-raspberry-pi-and-the-iot-in-c/59-raspberry-pi-and-the-iot-in-c-memory-mapped-gpio
11+}
12+
813 uses
914 Classes, SysUtils;
1015
@@ -18,7 +23,8 @@
1823 { Abaixo, rpi4.doc indica que a documentação precisa ser atualizada para o
1924 rpi4. Futuramente troque doc.ok, por rpi3.doc.ok. caso a documentação só faça
2025 sentido no rpi4, use rpi4.doc.ok. Verifique depois como lidar com documentação
21- alternativa no PasDOC }
26+ alternativa no PasDOC. Eu recomendo que seja feita uma revisão linha a linha
27+ principalmente naquelas que mapeiam caracterísiticas físicas do RPI }
2228
2329 { Para criar um novo record de periférico, inclua de forma privada um ou mais
2430 campos para o seletor (no caso de haver mais de um periférico do mesmo tipo) e
@@ -88,6 +94,8 @@
8894 end;
8995
9096 (* doc.ok *)
97+ (* rpi4.doc O RPI4 tem 58 GPIOs, mas estes 4 GPIOs a mais no tem função, logo
98+ acredito que seja apenas questão de mudar a enumeração abaixo *)
9199 //: Este tipo define um subconjunto de números que variam de 0 a 53 e que
92100 //: serve para representar cada um dos 54 GPIOs disponíveis no Raspberry PI 3
93101 //: (segundo o datasheet do BCM2837).
@@ -601,6 +609,11 @@
601609 end;
602610
603611 (* doc.ok *)
612+ (* rpi4.doc No RPI4 existem 8 controladores BSC, dentre os quais o BSC2 e o
613+ BSC7 são dedicados para uso com HDMI. Provavelmente existem GPIOs para acesso
614+ aos novos BSC, consulte o datasheet. A enumeração abaixo provavelmente vai
615+ precisar ser alterada no RPI4 *)
616+
604617 //: Existem 3 controladores BSC principais: BSC0, BSC1 e BSC2. O BSC2 é usado
605618 //: exclusivamente pelo HDMI e não deve ser usado em programas, por isso
606619 //: apenas os controladores 0 e 1 são acessíveis. O BSC1 encontra-se nos GPIO
@@ -610,7 +623,7 @@
610623 //:
611624 //: Algumas implementações acessam o I2C por meio de um file descriptor e
612625 //: execuções da função "ioctl". A título de informação, o dispositivo
613- //: "/dev/i2c-1" correspomde ao BSC1. Esta enumeração lista apenas os
626+ //: "/dev/i2c-1" corresponde ao BSC1. Esta enumeração lista apenas os
614627 //: controladores que são efetivamente acessáveis, atualmente o BSC0 e o BSC1
615628 //: @Value(icBSC0 Indica que estamos acessando o controlador 0)
616629 //: @Value(icBSC1 Indica que estamos acessando o controlador 1, também
@@ -1007,6 +1020,7 @@
10071020 //: dois dispositivos simultaneamente no mesmo programa)
10081021 TCustomPasRipherals = class
10091022 private
1023+ FCPUInfo: String;
10101024 FPeripherals: PUInt32;
10111025 FRunningAsRoot: Boolean;
10121026
@@ -1018,6 +1032,12 @@
10181032 function GetLevels(ALevelBank: TPRGPIOLevelBank): UInt32;
10191033 function GetModes(AModeBank: TGPIOModeBank): UInt32;
10201034 function GetState: TSavedState;
1035+
1036+ function GetCPUInfo: String;
1037+ function GetHardware: String;
1038+ function GetRevision: String;
1039+ function GetSerial: String;
1040+ function GetModel: String;
10211041 function GetInfo: String;
10221042
10231043 procedure SetLevels(ALevelBank: TPRGPIOLevelBank; ALevels: UInt32);
@@ -1032,7 +1052,9 @@
10321052
10331053 //: Use esta função para obter uma máscara com as características indicadas
10341054 function GetBitsMask(ABitIndex: UInt8; ABitsCount: UInt8): UInt32;
1035-
1055+ //: Use esta função para obter o endereço base dos periféricos e seu
1056+ //: tamanho. Essas informações são usadas no mapeamento da memória, durante
1057+ //: a criaço de um instância da classe atual
10361058 procedure PeripheralsBaseAddressAndSize(out ABaseAdddress: UInt32; out ASize: UInt32);
10371059
10381060 procedure NanoSleep(ANanoSeconds: Uint16);
@@ -1052,6 +1074,7 @@
10521074 property GPIOLevels[ALevelBank: TPRGPIOLevelBank]: UInt32 read GetLevels write SetLevels;
10531075 property GPIOModes[AModeBank: TGPIOModeBank]: UInt32 read GetModes write SetModes;
10541076 property State: TSavedState read GetState write SetState;
1077+
10551078 property Info: String read GetInfo;
10561079 public
10571080 constructor Create; virtual;
@@ -1106,7 +1129,7 @@
11061129 implementation
11071130
11081131 uses
1109- StrUtils, Math, BaseUnix, Errors;
1132+ StrUtils, Math, BaseUnix, Errors, RegExpr, UBCMHost;
11101133
11111134 const
11121135 // A senha é usada em algumas situações e corresponde ao binário
@@ -1132,7 +1155,9 @@
11321155 // eles não são usados diretamente, e sim em termos de bytes a partir do
11331156 // início da memória mapeada, no caso de uma inicialização com privilégios
11341157 // administrativos, por isso as constantes com o mesmo nome, mas com sufixo
1135- // "OFFSET" (mais adiante) é que são usadas
1158+ // "OFFSET" (mais adiante) é que são usadas. A saída do comando
1159+ // "sudo cat /proc/iomem" mostra alguns destes endereços, concatenados com o
1160+ // endereço base de periféricos ($3F000000 no Pi3 e $FE000000 no Pi4)
11361161 CLOCK_BASE = $101000;
11371162 GPIO_BASE = $200000;
11381163 BSC0_BASE = $205000;
@@ -2412,8 +2437,9 @@
24122437 FRunningAsRoot := FpGetuid = 0;
24132438
24142439 // Caso o usuário seja root, usamos /dev/mem que tem acesso completo a
2415- // memória, do contrário /dev/gpiomem que só é capaz de manipular os
2416- // registradores do GPIO
2440+ // memória e a todos os periféricos, do contrário usamos /dev/gpiomem que só é
2441+ // capaz de manipular os registradores do GPIO, único perifério acessível
2442+ // neste caso
24172443 if FRunningAsRoot then
24182444 PeripheralsFileDescriptor := FpOpen('/dev/mem', O_RDWR or O_SYNC)
24192445 else
@@ -2426,18 +2452,18 @@
24262452 // 4096 bytes. Caso len tenha valores de 4097 a 8192, Fpmmap vai ler 8192
24272453 // bytes e assim sucessivamente. Isso acontece porque esta função lê
24282454 // páginas de tamanho fixo e igual a múltiplos de 4096. Ao carregarmos
2429- // apenas o GPIO, a memória necessária é de apenas 180 Bytes ($B4), de
2455+ // apenas o GPIO, a memória necessária é de apenas 179 Bytes ($B3), de
24302456 // acordo com a saída de sudo cat /proc/iomem, que é menor que 4096 e
24312457 // portanto, usar este valor de forma fixa quando /dev/gpiomem for usado,
24322458 // é satisfatório. Quando estamos rodando o programa como root, usamos
2433- // "PeripheralsSize" e "PeripheralsBaseAddressAndSize div PAGE_SIZE" como
2434- // offset porque a função FpMMap é equivalente a função de api mmap2, onde
2435- // o último parâmetro não representa um offset em bytes, mas sim em
2436- // páginas de tamanho fixo e igual a 4K. No RPI3 PeripheralsBaseAddress é
2437- // $3F000000 e se estivéssemos usando uma função equivalente a mmap apenas
2438- // este valor seria suficiente em Offset, mas como a função FpMMap é um
2439- // alias para mmap2, precisamos dividir esse valor pelo tamanho da página
2440- // (4096)
2459+ // "PeripheralsSize" e "PeripheralsBaseAddress div PAGE_SIZE" como offset
2460+ // porque a função FpMMap é equivalente a função de api mmap2, onde o
2461+ // último parâmetro não representa um offset em bytes, mas sim em páginas
2462+ // de tamanho fixo e igual a 4K. No RPI3, por exemplo,
2463+ // PeripheralsBaseAddress é $3F000000 e se estivéssemos usando uma função
2464+ // equivalente a mmap apenas este valor seria suficiente em Offset, mas
2465+ // como a função FpMMap é um alias para mmap2, precisamos dividir esse
2466+ // valor pelo tamanho da página (4096)
24412467 if not FRunningAsRoot then
24422468 FPeripherals := FpMMap(nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, PeripheralsFileDescriptor, 0)
24432469 else
@@ -2460,11 +2486,9 @@
24602486 //WriteLn('Endereço que contém o nome: ',IntToHex(UInt32(GPIOBaseAddress + (($110 and $000FFFFF) shr 2)),10));
24612487 //WriteLn(
24622488 //
2463- //(GPIOBaseAddress + (($110 and $000FFFFF) shr 2))^
2489+ //PChar(GPIOBaseAddress + (($110 and $000FFFFF) shr 2))
24642490 //
24652491 //);
2466-
2467-
24682492 ////////////////
24692493
24702494
@@ -2588,8 +2612,109 @@
25882612 end;
25892613 end;
25902614
2615+function TCustomPasRipherals.GetCPUInfo: String;
2616+const
2617+ CPUINFO_PATH = '/proc/cpuinfo';
2618+var
2619+ LCPUInfo: TextFile;
2620+ Line: String;
2621+begin
2622+ Result := '';
2623+
2624+ if FCPUInfo = '' then
2625+ begin
2626+ AssignFile(LCPUInfo,CPUINFO_PATH);
2627+ try
2628+ Filemode := fmOpenRead;
2629+ Reset(LCPUInfo);
2630+
2631+ while not Eof(LCPUInfo) do
2632+ begin
2633+ ReadLn(LCPUInfo,Line);
2634+ FCPUInfo := FCPUInfo + Line + #10;
2635+ end;
2636+
2637+ FCPUInfo := Trim(FCPUInfo);
2638+ finally
2639+ CloseFile(LCPUInfo);
2640+ end;
2641+ end;
2642+
2643+ Result := FCPUInfo;
2644+end;
2645+
2646+function TCustomPasRipherals.GetHardware: String;
2647+begin
2648+ Result := '';
2649+
2650+ with TRegExpr.Create('Hardware\s*:\s*(.*)') do
2651+ try
2652+ ModifierS := False;
2653+
2654+ if Exec(GetCPUInfo) then
2655+ Result := Trim(Match[1]);
2656+ finally
2657+ Free;
2658+ end;
2659+end;
2660+
2661+function TCustomPasRipherals.GetRevision: String;
2662+begin
2663+ Result := '';
2664+
2665+ with TRegExpr.Create('Revision\s*:\s*(.*)') do
2666+ try
2667+ ModifierS := False;
2668+
2669+ if Exec(GetCPUInfo) then
2670+ Result := Trim(Match[1]);
2671+ finally
2672+ Free;
2673+ end;
2674+end;
2675+
2676+function TCustomPasRipherals.GetSerial: String;
2677+begin
2678+ Result := '';
2679+
2680+ with TRegExpr.Create('Serial\s*:\s*(.*)') do
2681+ try
2682+ ModifierS := False;
2683+
2684+ if Exec(GetCPUInfo) then
2685+ Result := Trim(Match[1]);
2686+ finally
2687+ Free;
2688+ end;
2689+end;
2690+
2691+function TCustomPasRipherals.GetModel: String;
2692+begin
2693+ Result := '';
2694+
2695+ with TRegExpr.Create('Model\s*:\s*(.*)') do
2696+ try
2697+ ModifierS := False;
2698+
2699+ if Exec(GetCPUInfo) then
2700+ Result := Trim(Match[1]);
2701+ finally
2702+ Free;
2703+ end;
2704+end;
2705+
25912706 function TCustomPasRipherals.GetInfo: String;
25922707 // -----------------------------------------------------------------------------
2708+procedure RPIInfo;
2709+begin
2710+ Result += '╔═══════════════════════════════════════════════════════════════════════════╗'#13#10;
2711+ Result += '║ Model.........: ' + Format('%-58s',[GetModel]) + '║'#13#10;
2712+ Result += '║ SoC...........: ' + Format('%-58s',[GetHardware]) + '║'#13#10;
2713+ Result += '║ Revision......: ' + Format('%-58s',[GetRevision]) + '║'#13#10;
2714+ Result += '║ Serial Number.: ' + Format('%-58s',[GetSerial]) + '║'#13#10;
2715+ Result += '╚═══════════════════════════════════════════════════════════════════════════╝'#13#10;
2716+end;
2717+
25932718 procedure GPIOInfo;
25942719 const
25952720 INFOLINE = '║ %-11u ║ %-19s ║ %-6s ║ %-14s ║ %-11s ║';
@@ -2668,6 +2793,7 @@
26682793 // -----------------------------------------------------------------------------
26692794 begin
26702795 Result := '';
2796+ RPIInfo;
26712797 GPIOInfo;
26722798
26732799 if FRunningAsRoot then
@@ -2699,9 +2825,9 @@
26992825
27002826 function TCustomPasRipherals.ClockBaseAddress: PUInt32;
27012827 begin
2702- // O DataSheet não faz uma referência ao endereço base usado aqui para o
2703- // clock. Nas páginas 107 e 108 existem 6 endereços que pouco tem a ver com
2704- // CLOCK_BASE, no entanto as bibliotecas WiringPi e BCM2835 usam o mesmo
2828+ // O DataSheet do BCM2835 não faz uma referência ao endereço base usado aqui
2829+ // para o clock. Nas páginas 107 e 108 existem 6 endereços que pouco tem a ver
2830+ // com CLOCK_BASE, no entanto as bibliotecas WiringPi e BCM2835 usam o mesmo
27052831 // offset e por isso eu assumi como verdade. Ainda sobre os endereços que
27062832 // constam no datasheet, eles foram agrupados por tipo (CTL e DIV), e isso
27072833 // causa uma certa confusão. Na verdade existem 6 registradores de 32 bits
@@ -2716,35 +2842,63 @@
27162842 Result := FPeripherals + CLOCK_BASE_OFFSET;
27172843 end;
27182844
2719-procedure TCustomPasRipherals.PeripheralsBaseAddressAndSize(out ABaseAdddress: UInt32; out ASize: UInt32);
2720-const
2721- SOC_RANGES_PATH = '/proc/device-tree/soc/ranges';
2722- SOC_RANGES_ADDRESS_OFFSET = 4;
2723-var
2724- Ranges: Integer;
2725- Buffer: array [0..3] of Byte;
2726-begin
2727- Buffer[0] := 0;
2728- Buffer[1] := 0;
2729- Buffer[2] := 0;
2730- Buffer[3] := 0;
2845+{
2846+Anteriormente a função abaixo usava uma leitura direta de
2847+/proc/device-tree/soc/ranges, que retorna uma sequencia de Bytes. O significado
2848+e a quantidade destes Bytes mudou entre o Pi3 e o Pi4, mas basicamente, dentre
2849+eles, existem 3 grupos de Bytes que ficam no começo dessa sequência. Observe os
2850+dois exemplos a seguir e sua posterior explicação:
27312851
2732- Ranges := FpOpen(SOC_RANGES_PATH,O_RDONLY);
2852+Pi3: 7E000000 3F000000 01000000
2853+Pi4: 7E000000 00000000FE000000 01800000
27332854
2734- if Ranges > 0 then
2735- try
2736- FpLseek(Ranges,SOC_RANGES_ADDRESS_OFFSET,SEEK_SET);
2737- if FpRead(Ranges,Buffer,SizeOf(Buffer)) = SizeOf(Buffer) then
2738- ABaseAdddress := Buffer[0] shl 24 or Buffer[1] shl 16 or Buffer[2] shl 8 or Buffer[3] shl 0;
2855+> Os primeiros quatro Bytes (32 bits) em todas as versões de Pi representam o
2856+ "endereço-base dos periféricos do barramento do CPU VideoCore", tal como
2857+ descrito no datasheet do BCM2835 e cujo valor é $7E000000. Este endereço é
2858+ mapeado para o endereço-base dos periféricos (vistos a seguir), os quais são
2859+ os endereços acessíveis por meio das bilbiotecas que acessam os periféricos do
2860+ Pi
2861+> No Pi3, os próximos quatro Bytes (32 bits) representam o endereço-base dos
2862+ periféricos que pode ser usado para mapeamento da memória para acesso aos
2863+ periféricos do Pi. Neste Pi, o valor é $3F000000
2864+> No Pi4, os próximos oito Bytes (64 bits) representam o endereço-base dos
2865+ periféricos que pode ser usado para mapeamento da memória para acesso aos
2866+ periféricos do Pi. Neste Pi, o valor é $00000000FE000000 (ou $FE000000)
2867+> Os próximos quatro Bytes (32 bits) em todas as versões de Pi representam o
2868+ tamanho em Bytes da memória ocupada pelo mapeamento dos periféricos. No Pi3
2869+ esse valor é $01000000 e no Pi4 esse valor é $01800000
2870+> Todas estas explicações, principalmente o tamanho de cada grupo de Bytes, foi
2871+ obtida por meio de "pescaria" de informaçes na web, isto é, não achei um site
2872+ que explicasse o formato de /proc/device-tree/soc/ranges, só achei pessoas
2873+ falando a respeito, mas sem citar qualquer fonte
27392874
2740- FpLseek(Ranges,8,SEEK_SET);
2741- if FpRead(Ranges,Buffer,SizeOf(Buffer)) = SizeOf(Buffer) then
2742- ASize := Buffer[0] shl 24 or Buffer[1] shl 16 or Buffer[2] shl 8 or Buffer[3] shl 0;
2743- finally
2744- FpClose(Ranges);
2745- end
2746- else
2747- raise EPasRipherals.Create('Não foi possível obter o endereço-base dos periféricos');
2875+Observando a saída de sudo cat /proc/iomem podemos ver que algumas saídas
2876+mostram o resultado do mapeamento de alguns periféricos, por exemplo, para o
2877+GPIO no Pi4 há a seguinte linha:
2878+
2879+fe200000.gpio gpio@7e200000
2880+
2881+Essa linha deve ser lida da seguinte forma:
2882+
2883+"O GPIO está acessível no endereço $FE200000, o qual mapeia (ou aponta) para o
2884+endereço $7E200000 do CPU VideoCore"
2885+
2886+No caso do GPIO, $200000, que foi somado a $7E000000 e $FE000000, é o offset,
2887+dentro do mapeamento dos periféricos, onde se encontra o GPIO. Os datasheets
2888+BCM2711 e BCM2835 mostram que o endereço do GPIO é $7E200000, porém o endereço
2889+que se deve usar ao acessar o GPIO deve ser o endereço mapeado, o qual é obtido
2890+a partir da função abaixo. Para mais informações sobre VideoCore, BCM e ARM,
2891+acesse https://en.wikipedia.org/wiki/VideoCore
2892+
2893+Outra curiosidade a respeito do VideoCore é que ele é a GPU e no Pi é a GPU que
2894+é inicializada antes do ARM, e talvez por isso que todo esse mapeamento seja
2895+necessário. Leia isso aqui: https://bootlin.com/blog/enabling-new-hardware-on-raspberry-pi-with-device-tree-overlays/
2896+}
2897+
2898+procedure TCustomPasRipherals.PeripheralsBaseAddressAndSize(out ABaseAdddress: UInt32; out ASize: UInt32);
2899+begin
2900+ ABaseAdddress := bcm_host_get_peripheral_address;
2901+ ASize := bcm_host_get_peripheral_size;
27482902 end;
27492903
27502904 function TCustomPasRipherals.GPIOBaseAddress: PUInt32;
旧リポジトリブラウザで表示