Difference between revisions of "Unit PlatformRPi4"
Line 38: | Line 38: | ||
---- | ---- | ||
− | '' | + | |
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi ARM physical to VC IO mapping''' <code> RPI4_VCIO_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_VCIO_ALIAS = BCM2838_VCIO_ALIAS;</code> | ||
+ | | style="width: 50%;"|The VCIO Alias (For ARM Physcial to VC IO translation) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi ARM physical to VC bus mapping''' <code> RPI4_VCBUS_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_VCBUS_ALIAS = BCM2838_VCBUS_C_ALIAS;</code> | ||
+ | | style="width: 50%;"|The currently selected VCBUS Alias (For ARM Physcial to VC Bus translation) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi secure world boot''' <code> RPI4_SECURE_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_SECURE_BOOT = $00000001;</code> | ||
+ | | style="width: 50%;"|If 1 then startup will attempt to switch back to secure world during boot process (Moved to ARMSecureBoot) | ||
+ | |- | ||
+ | | <code>RPI4_SECURE_BOOT_OFFSET = $000000D4;</code> | ||
+ | | The address of the Secure Boot marker in the ARM boot stub | ||
+ | |- | ||
+ | | <code>RPI4_SECURE_BOOT_MARKER = $58495052;</code> | ||
+ | | The Secure Boot marker (ASCII "RPIX") | ||
+ | |- | ||
+ | | <code>RPI4_SECURE_BOOT_CIRCLE = $53514946;</code> | ||
+ | | The alternate Secure Boot marker (ASCII "FIQS") (As used by Circle) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi address of StartupHandler on reset''' <code> RPI4_STARTUP_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_STARTUP_ADDRESS = $00008000;</code> | ||
+ | | style="width: 50%;"|Obtain from linker | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi page directory address and size''' <code> RPI4_PAGE_DIRECTORY_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_PAGE_DIRECTORY_BASE = $00002000;</code> | ||
+ | | style="width: 50%;"|Place the first level Page Directory after the interrupt vectors at 0x00001000 and before the first level Page Table at 0x00004000 | ||
+ | |- | ||
+ | | <code>RPI4_PAGE_DIRECTORY_SIZE = SIZE_4K;</code> | ||
+ | | ARM Cortex A72 first level Page Table is up to 4KB in size (512 64 bit (8 byte) entries) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi page table address and size''' <code> RPI4_PAGE_TABLE_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_PAGE_TABLE_BASE = $00004000;</code> | ||
+ | | style="width: 50%;"|Place the second level Page Table after the first level Page Directory at 0x00002000 and before the code start at 0x00008000 | ||
+ | |- | ||
+ | | <code>RPI4_PAGE_TABLE_SIZE = SIZE_16K;</code> | ||
+ | | ARM Cortex A72 second level Page Table is exactly 16KB in size (4 x 512 64 bit (8 byte) entries) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi vector table address and size''' <code> RPI4_VECTOR_TABLE_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_VECTOR_TABLE_BASE = $00001000;</code> | ||
+ | | style="width: 50%;"|Place the Interrupt Vector Table at 0x00001000 before the code start at 0x00008000 | ||
+ | |- | ||
+ | | <code>RPI4_VECTOR_TABLE_SIZE = SIZE_64;</code> | ||
+ | | The Interrupt Vector Table is exactly 64 bytes (16 32 bit (4 byte) entries) | ||
+ | |- | ||
+ | | <code>RPI4_VECTOR_TABLE_COUNT = 8;</code> | ||
+ | | The Interrupt Vector Table contains 8 entries on an ARMv7 device | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi CPU count''' <code> RPI4_CPU_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_CPU_COUNT = BCM2838_CPU_COUNT;</code> | ||
+ | | style="width: 50%;"| | ||
+ | |- | ||
+ | | <code>RPI4_CPU_BOOT = CPU_ID_0;</code> | ||
+ | | | ||
+ | |- | ||
+ | | <code>RPI4_CPU_MASK = CPU_AFFINITY_0 or CPU_AFFINITY_1 or CPU_AFFINITY_2 or CPU_AFFINITY_3;</code> | ||
+ | | | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi SWI''' <code> RPI4_SWI_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_SWI_COUNT = 256;</code> | ||
+ | | style="width: 50%;"|Number of available SWI entries | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi interrupt''' <code> RPI4_GIC_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_GIC_UNAVAILABLE = 0;</code> | ||
+ | | style="width: 50%;"| | ||
+ | |- | ||
+ | | <code>RPI4_GIC_AVAILABLE = 1;</code> | ||
+ | | | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi core timer''' <code> RPI4_CORE_TIMER_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_CORE_TIMER_PRESCALER = $25ED098;</code> | ||
+ | | style="width: 50%;"|Divide the Crystal Clock by 54 to give a 1MHz Core Timer | ||
+ | |- | ||
+ | | <code>RPI4_CORE_TIMER_FREQUENCY = 1000000;</code> | ||
+ | | The Core Timer frequency from the prescaler setting above | ||
+ | |- | ||
+ | | <code>RPI4_GENERIC_TIMER_FREQUENCY = 1000000;</code> | ||
+ | | The ARM Generic Timer frequency from the prescaler setting above | ||
+ | |- | ||
+ | |colspan="2"| | ||
+ | |- | ||
+ | | <code>RPI4_CORE_TIMER_PRESCALER = $80000000;</code> | ||
+ | | Divide the Crystal Clock by 1 to give a 54MHz Core Timer | ||
+ | |- | ||
+ | | <code>RPI4_CORE_TIMER_FREQUENCY = 54000000;</code> | ||
+ | | The Core Timer frequency from the prescaler setting above | ||
+ | |- | ||
+ | | <code>RPI4_GENERIC_TIMER_FREQUENCY = 54000000;</code> | ||
+ | | The ARM Generic Timer frequency from the prescaler setting above | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi kernel image name''' <code> RPI4_KERNEL_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_KERNEL_NAME = 'kernel7l.img';</code> | ||
+ | | style="width: 50%;"| | ||
+ | |- | ||
+ | | <code>RPI4_KERNEL_NAME = 'kernel8.img';</code> | ||
+ | | | ||
+ | |- | ||
+ | | <code>RPI4_KERNEL_CONFIG = 'config.txt';</code> | ||
+ | | | ||
+ | |- | ||
+ | | <code>RPI4_KERNEL_COMMAND = 'cmdline.txt';</code> | ||
+ | | | ||
+ | |- | ||
+ | | <code>RPI4_FIRMWARE_FILES = 'start4.elf,fixup4.dat' + ',armstub32-rpi4.bin' + ',armstub64-rpi4.bin';</code> | ||
+ | | | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi GPIO activity LED (GPIO Pin 42)''' <code> RPI4_GPIO_ACTLED_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPFSEL = BCM2838_GPFSEL4;</code> | ||
+ | | style="width: 50%;"|GPFSEL register for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPSET = BCM2838_GPSET1;</code> | ||
+ | | GPSET register for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPCLR = BCM2838_GPCLR1;</code> | ||
+ | | GPCLR register for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPPUD = BCM2838_GPPUD2;</code> | ||
+ | | GPPUD register for ACT LED | ||
+ | |- | ||
+ | |colspan="2"| | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPFSHIFT = 6;</code> | ||
+ | | GPFSEL register shift for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPFMASK = BCM2838_GPFSEL_MASK;</code> | ||
+ | | GPFSEL register mask for ACT LED | ||
+ | |- | ||
+ | |colspan="2"| | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPSHIFT = (42 - 32);</code> | ||
+ | | GPSET/GPCLR register shift for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPMASK = BCM2838_GPSET_MASK;</code> | ||
+ | | GPSET/GPCLR register mask for ACT LED | ||
+ | |- | ||
+ | |colspan="2"| | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPPUDSHIFT = 20;</code> | ||
+ | | GPPUD register shift for ACT LED | ||
+ | |- | ||
+ | | <code>RPI4_GPIO_ACTLED_GPPUDMASK = BCM2838_GPPUD_MASK;</code> | ||
+ | | GPPUD register mask for ACT LED | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi mailbox timeout''' <code> RPI4_MAILBOX_TIMEOUT_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_MAILBOX_TIMEOUT = 100;</code> | ||
+ | | style="width: 50%;"|Default timeout to wait for mailbox calls to complete (Milliseconds) | ||
+ | |- | ||
+ | | <code>RPI4_MAILBOX_TIMEOUT_EX = 1000;</code> | ||
+ | | Extended timeout to wait for mailbox calls to complete (Milliseconds) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi local mailbox''' <code> RPI4_LOCAL_MAILBOX_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_LOCAL_MAILBOX_TIMEOUT = 100;</code> | ||
+ | | style="width: 50%;"|Default timeout to wait for local mailbox calls to complete (Milliseconds) | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
+ | <div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;"> | ||
+ | <div style="font-size: 14px; padding-left: 12px;">'''RPi framebuffer''' <code> RPI4_FRAMEBUFFER_* </code></div> | ||
+ | <div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;"> | ||
+ | {| class="wikitable" style="font-size: 14px; background: white;" | ||
+ | |- | ||
+ | | <code>RPI4_FRAMEBUFFER_DESCRIPTION = 'BCM2838 Framebuffer';</code> | ||
+ | | style="width: 50%;"| | ||
+ | |- | ||
+ | |} | ||
+ | </div></div> | ||
+ | <br /> | ||
=== Type definitions === | === Type definitions === |
Revision as of 04:36, 25 June 2021
Return to Unit Reference
Contents
[hide]Description
Ultibo Platform interface unit for Raspberry Pi 4
Note: The RPi4B has the Activity LED connected to GPIO Pin 42 (Power LED is only accessible via the GPIO expander driver)
Detecting the GIC or legacy interrupt controller
The Raspberry Pi 4 contains a new GIC interrupt controller which includes modern features like the ability to service interrupts on all available cores, a full set of software generated processor to processor interrupts and complete FIQ handling for all interrupt sources.
The Pi 4 also retains and expands the legacy interrupt controller used on earlier Pi models with support for routing interrupts to any core and FIQ handling for all interrupt sources.
The documentation at https://www.raspberrypi.org/documentation/configuration/config-txt/boot.md states that the setting enable_gic=0 or 1 can be used to select between the legacy and GIC interrupt controllers and that the GIC (enable_gic=1) is the default.
Testing however shows this is not completely correct, if no config.txt file exists and no device tree DTB files are present then the current firmware appears to enable the legacy interrupt controller by default.
If device tree DTB files containing a compatible GIC node are available on the SD card during boot the firmware will enable the GIC, this appears to happen regardless of the setting in config.txt and a value of enable_gic=0 will be ignored in favour of the device tree setting.
If the legacy interrupt controller is enabled and Ultibo configures the GIC controller during boot it will receive no interrupts and appear to hang (four color screen).
While it might be possible to read the SD card during boot, check for a config.txt and parse it to determine the value of the enable_gic setting, to be fully functional this process would also need to parse the device tree information (if available) and check for a compatible GIC node. Even then that doesn't account for booting from USB, network or some other source and all of that would have to happen very early in the boot sequence to be usable.
To make matters worse there doesn't appear to be a documented way to detect which interrupt controller is enabled by reading a register value, the GIC even behaves as though it is working when the legacy controller is enabled but no interrupts are received.
To ensure a level of reliability regardless of what firmware and files and configuration settings are present Ultibo implements drivers for both the GIC and legacy interrupt controllers and includes a detection mechanism during early stage boot.
In simple terms the boot process configures the GIC and then installs an interrupt handler for the generic virtual timer and configures the timer to fire in 1ms before enabling interrupts. It then waits 2ms and disables interrupts, unconfigures the timer and deregisters the interrupt handler.
If the test worked the local variable GICAvailable will have been set by the handler to RPI4_GIC_AVAILABLE, if not the variable will remain at RPI4_GIC_UNAVAILABLE and the boot process will proceed to configure the legacy interrupt controller for use.
This is not an ideal mechanism and could potentially fail for other reasons (although it is carefully constructed to avoid many potential failures) but at present is the best option for allowing the boot process to succeed regardless of the firmware behavior.
Constants
RPI4_VCIO_*
RPI4_VCBUS_*
RPI4_SECURE_*
RPI4_STARTUP_*
RPI4_PAGE_DIRECTORY_*
RPI4_PAGE_TABLE_*
RPI4_VECTOR_TABLE_*
RPI4_CPU_*
RPI4_SWI_*
RPI4_GIC_*
RPI4_CORE_TIMER_*
RPI4_KERNEL_*
RPI4_GPIO_ACTLED_*
RPI4_MAILBOX_TIMEOUT_*
RPI4_LOCAL_MAILBOX_*
RPI4_FRAMEBUFFER_*
Type definitions
To be documented
Public variables
RPi4 specific Ultibo variables
RPi4Initialized:Boolean;
|
RPi4CNTVOFFLow:LongWord = 0;
|
The low 32 bits of the Virtual Counter Offset register at boot time (CPU0 only) (Set by Startup) Must be initialized to remain in .data or else rewritten to zero with .bss |
RPi4CNTVOFFHigh:LongWord = 0;
|
The high 32 bits of the Virtual Counter Offset register at boot time (CPU0 only) (Set by Startup) Must be initialized to remain in .data or else rewritten to zero with .bss |
Timer register
TimerRegisters:PBCM2838SystemTimerRegisters;
|
Mailbox register
Mailbox0Registers:PBCM2838Mailbox0Registers;
|
Mailbox1Registers:PBCM2838Mailbox1Registers;
|
Interrupt device
GICDevice:PGICDevice;
|
GICAvailable:LongWord = RPI4_GIC_AVAILABLE;
|
The status of the GIC interrupt controller, determined during boot. |
System call
SystemCallEntries:array[0..RPI4_SWI_COUNT - 1] of TSystemCallEntry;
|
Watchdog register
WatchdogRegisters:PBCM2838PMWatchdogRegisters;
|
ARM local register
ARMLocalRegisters:PBCM2838ARMLocalRegisters;
|
Virtual GPIO
VirtualGPIOBuffer:TBCM2838VirtualGPIOBuffer;
|
Function declarations
Initialization functions
RPi4 platform functions
procedure RPi4PageTableInit;
procedure RPi4PageTableInitLegacy;
function RPi4MailboxReceive(Mailbox,Channel:LongWord):LongWord;
procedure RPi4MailboxSend(Mailbox,Channel,Data:LongWord);
function RPi4MailboxCall(Mailbox,Channel,Data:LongWord; var Response:LongWord):LongWord;
function RPi4MailboxCallEx(Mailbox,Channel,Data:LongWord; var Response:LongWord; Timeout:LongWord):LongWord;
function RPi4MailboxPropertyCall(Mailbox,Channel:LongWord; Data:Pointer; var Response:LongWord):LongWord;
function RPi4MailboxPropertyCallEx(Mailbox,Channel:LongWord; Data:Pointer; var Response:LongWord; Timeout:LongWord):LongWord;
function RPi4RequestExIRQ(CPUID,Number:LongWord; Handler:TInterruptHandler; HandlerEx:TInterruptExHandler; Parameter:Pointer):LongWord;
function RPi4ReleaseExIRQ(CPUID,Number:LongWord; Handler:TInterruptHandler; HandlerEx:TInterruptExHandler; Parameter:Pointer):LongWord;
function RPi4RequestExFIQ(CPUID,Number:LongWord; Handler:TInterruptHandler; HandlerEx:TInterruptExHandler; Parameter:Pointer):LongWord;
function RPi4ReleaseExFIQ(CPUID,Number:LongWord; Handler:TInterruptHandler; HandlerEx:TInterruptExHandler; Parameter:Pointer):LongWord;
function RPi4RequestIPI(CPUID,Number:LongWord; Handler:TIPIHandler; Parameter:Pointer):LongWord;
function RPi4ReleaseIPI(CPUID,Number:LongWord; Handler:TIPIHandler; Parameter:Pointer):LongWord;
function RPi4RegisterInterrupt(Number,Mask,Priority,Flags:LongWord; Handler:TSharedInterruptHandler; Parameter:Pointer):LongWord;
function RPi4DeregisterInterrupt(Number,Mask,Priority,Flags:LongWord; Handler:TSharedInterruptHandler; Parameter:Pointer):LongWord;
function RPi4RegisterSystemCallEx(CPUID,Number:LongWord; Handler:TSystemCallHandler; HandlerEx:TSystemCallExHandler):LongWord;
function RPi4DeregisterSystemCallEx(CPUID,Number:LongWord; Handler:TSystemCallHandler; HandlerEx:TSystemCallExHandler):LongWord;
function RPi4GetInterruptEntry(Number,Instance:LongWord; var Interrupt:TInterruptEntry):LongWord;
function RPi4GetLocalInterruptEntry(CPUID,Number,Instance:LongWord; var Interrupt:TInterruptEntry):LongWord;
function RPi4GetSoftwareInterruptEntry(CPUID,Number,Instance:LongWord; var Interrupt:TInterruptEntry):LongWord;
function RPi4GetSystemCallEntry(Number:LongWord):TSystemCallEntry;
function RPi4SystemGetCommandLine:String;
function RPi4CPUGetMemory(var Address:PtrUInt; var Length:UInt64):LongWord;
function RPi4GPUGetMemory(var Address:PtrUInt; var Length:UInt64):LongWord;
function RPi4BoardGetModel:LongWord;
function RPi4BoardGetSerial:Int64;
function RPi4BoardGetRevision:LongWord;
function RPi4BoardGetMACAddress:String;
function RPi4FirmwareGetRevision:LongWord;
function RPi4FirmwareGetThrottled:LongWord;
function RPi4PowerGetWait(PowerId:LongWord):LongWord;
function RPi4PowerGetState(PowerId:LongWord):LongWord;
function RPi4PowerSetState(PowerId,State:LongWord; Wait:Boolean):LongWord;
function RPi4ClockGetCount:LongWord;
function RPi4ClockGetRate(ClockId:LongWord):LongWord;
function RPi4ClockSetRate(ClockId,Rate:LongWord; Turbo:Boolean):LongWord;
function RPi4ClockGetState(ClockId:LongWord):LongWord;
function RPi4ClockSetState(ClockId,State:LongWord):LongWord;
function RPi4ClockGetMinRate(ClockId:LongWord):LongWord;
function RPi4ClockGetMaxRate(ClockId:LongWord):LongWord;
function RPi4TurboGetState(TurboId:LongWord):LongWord;
function RPi4TurboSetState(TurboId,State:LongWord):LongWord;
function RPi4VoltageGetValue(VoltageId:LongWord):LongWord;
function RPi4VoltageSetValue(VoltageId,Value:LongWord):LongWord;
function RPi4VoltageGetMinValue(VoltageId:LongWord):LongWord;
function RPi4VoltageGetMaxValue(VoltageId:LongWord):LongWord;
function RPi4TemperatureGetCurrent(TemperatureId:LongWord):LongWord;
function RPi4TemperatureGetMaximum(TemperatureId:LongWord):LongWord;
function RPi4GPUMemoryAllocate(Length,Alignment,Flags:LongWord):THandle;
function RPi4GPUMemoryRelease(Handle:THandle):LongWord;
function RPi4GPUMemoryLock(Handle:THandle):LongWord;
function RPi4GPUMemoryUnlock(Handle:THandle):LongWord;
function RPi4GPUExecuteCode(Address:Pointer; R0,R1,R2,R3,R4,R5:LongWord):LongWord;
function RPi4DispmanxHandleGet(Resource:THandle):THandle;
function RPi4EDIDBlockGet(Block:LongWord; Buffer:Pointer; Length:LongWord):LongWord;
function RPi4FramebufferAllocate(Alignment:LongWord; var Address,Length:LongWord):LongWord;
function RPi4FramebufferRelease:LongWord;
function RPi4FramebufferSetState(State:LongWord):LongWord;
function RPi4FramebufferGetDimensions(var Width,Height,Top,Bottom,Left,Right:LongWord):LongWord;
function RPi4FramebufferGetPhysical(var Width,Height:LongWord):LongWord;
function RPi4FramebufferSetPhysical(var Width,Height:LongWord):LongWord;
function RPi4FramebufferTestPhysical(var Width,Height:LongWord):LongWord;
function RPi4FramebufferGetVirtual(var Width,Height:LongWord):LongWord;
function RPi4FramebufferSetVirtual(var Width,Height:LongWord):LongWord;
function RPi4FramebufferTestVirtual(var Width,Height:LongWord):LongWord;
function RPi4FramebufferGetDepth(var Depth:LongWord):LongWord;
function RPi4FramebufferSetDepth(var Depth:LongWord):LongWord;
function RPi4FramebufferTestDepth(var Depth:LongWord):LongWord;
function RPi4FramebufferGetPixelOrder(var Order:LongWord):LongWord;
function RPi4FramebufferSetPixelOrder(var Order:LongWord):LongWord;
function RPi4FramebufferTestPixelOrder(var Order:LongWord):LongWord;
function RPi4FramebufferGetAlphaMode(var Mode:LongWord):LongWord;
function RPi4FramebufferSetAlphaMode(var Mode:LongWord):LongWord;
function RPi4FramebufferTestAlphaMode(var Mode:LongWord):LongWord;
function RPi4FramebufferGetPitch:LongWord;
function RPi4FramebufferGetOffset(var X,Y:LongWord):LongWord;
function RPi4FramebufferSetOffset(var X,Y:LongWord):LongWord;
function RPi4FramebufferTestOffset(var X,Y:LongWord):LongWord;
function RPi4FramebufferGetOverscan(var Top,Bottom,Left,Right:LongWord):LongWord;
function RPi4FramebufferSetOverscan(var Top,Bottom,Left,Right:LongWord):LongWord;
function RPi4FramebufferTestOverscan(var Top,Bottom,Left,Right:LongWord):LongWord;
function RPi4FramebufferGetPalette(Buffer:Pointer;Length:LongWord):LongWord;
function RPi4FramebufferSetPalette(Start,Count:LongWord; Buffer:Pointer; Length:LongWord):LongWord;
function RPi4FramebufferTestPalette(Start,Count:LongWord; Buffer:Pointer; Length:LongWord):LongWord;
function RPi4FramebufferTestVsync:LongWord;
function RPi4FramebufferSetVsync:LongWord;
function RPi4FramebufferSetBacklight(Brightness:LongWord):LongWord;
function RPi4FramebufferGetNumDisplays(var NumDisplays:LongWord):LongWord;
function RPi4FramebufferGetDisplayId(DisplayNum:LongWord):LongWord;
function RPi4FramebufferSetDisplayNum(DisplayNum:LongWord):LongWord;
function RPi4FramebufferGetDisplaySettings(DisplayNum:LongWord; var DisplaySettings:TDisplaySettings):LongWord;
function RPi4FramebufferDisplayIdToName(DisplayId:LongWord):String;
function RPi4TouchGetBuffer(var Address:PtrUInt):LongWord;
function RPi4TouchSetBuffer(Address:PtrUInt):LongWord;
function RPi4VirtualGPIOGetBuffer(var Address:PtrUInt):LongWord;
function RPi4VirtualGPIOSetBuffer(Address:PtrUInt):LongWord;
function RPi4CursorSetDefault:LongWord;
function RPi4CursorSetInfo(Width,Height,HotspotX,HotspotY:LongWord; Pixels:Pointer; Length:LongWord):LongWord;
function RPi4CursorSetState(Enabled:Boolean; X,Y:LongWord; Relative:Boolean):LongWord;
function RPi4DMAGetChannels:LongWord;
function RPi4VirtualGPIOOutputSet(Pin,Level:LongWord):LongWord;
function RPi4VirtualGPIOFunctionSelect(Pin,Mode:LongWord):LongWord;
RPi4 thread functions
procedure RPi4SchedulerInit;
procedure RPi4SchedulerStart(CPUID:LongWord);
RPi4 SWI functions
function RPi4DispatchSWI(CPUID:LongWord; Thread:TThreadHandle; Request:PSystemCallRequest):TThreadHandle;
RPi4 clock functions
procedure RPi4ClockInterrupt(Parameter:Pointer);
procedure RPi4ClockUpdate(Cycles:LongWord; var Last:LongWord);
RPi4 scheduler functions
function RPi4SchedulerInterrupt(CPUID:LongWord; Thread:TThreadHandle; Parameter:Pointer):TThreadHandle;
procedure RPi4SchedulerUpdate(Cycles:LongWord; var Last:LongWord);
procedure RPi4SchedulerSystemCall(Request:PSystemCallRequest);
RPi4 framebuffer functions
function RPi4FramebufferDeviceAllocate(Framebuffer:PFramebufferDevice; Properties:PFramebufferProperties):LongWord;
function RPi4FramebufferDeviceAllocateAlt(Framebuffer:PFramebufferDevice; Properties:PFramebufferProperties):LongWord;
function RPi4FramebufferDeviceRelease(Framebuffer:PFramebufferDevice):LongWord;
function RPi4FramebufferDeviceBlank(Framebuffer:PFramebufferDevice; Blank:Boolean):LongWord;
function RPi4FramebufferDeviceCommit(Framebuffer:PFramebufferDevice; Address:PtrUInt; Size,Flags:LongWord):LongWord;
function RPi4FramebufferDeviceSetBacklight(Framebuffer:PFramebufferDevice; Brightness:LongWord):LongWord;
function RPi4FramebufferDeviceSetProperties(Framebuffer:PFramebufferDevice;Properties:PFramebufferProperties):LongWord;
RPi4 helper functions
procedure RPi4BootBlink;
procedure RPi4BootConsoleWriteEx(const Value:String; X,Y:LongWord);
function RPi4ConvertPowerIdRequest(PowerId:LongWord):LongWord;
function RPi4ConvertPowerStateRequest(PowerState:LongWord):LongWord;
function RPi4ConvertPowerStateResponse(PowerState:LongWord):LongWord;
function RPi4ConvertClockIdRequest(ClockId:LongWord):LongWord;
function RPi4ConvertClockStateRequest(ClockState:LongWord):LongWord;
function RPi4ConvertClockStateResponse(ClockState:LongWord):LongWord;
function RPi4ConvertVoltageIdRequest(VoltageId:LongWord):LongWord;
function RPi4ConvertTemperatureIdRequest(TemperatureId:LongWord):LongWord;
Return to Unit Reference