{$IFNDEF FPC_DOTTEDUNITS} unit raspi2; {$ENDIF FPC_DOTTEDUNITS} {$goto on} {$INLINE ON} interface type TBitvector32 = bitpacked array[0..31] of 0..1; const PeripheralBase = $3F000000; GPFSEL1 = PeripheralBase + $00200004; GPSET0 = PeripheralBase + $0020001C; GPCLR0 = PeripheralBase + $00200028; GPPUD = PeripheralBase + $00200094; GPPUDCLK0 = PeripheralBase + $00200098; AUX_ENABLES = PeripheralBase + $00215004; AUX_MU_IO_REG = PeripheralBase + $00215040; AUX_MU_IER_REG = PeripheralBase + $00215044; AUX_MU_IIR_REG = PeripheralBase + $00215048; AUX_MU_LCR_REG = PeripheralBase + $0021504C; AUX_MU_MCR_REG = PeripheralBase + $00215050; AUX_MU_LSR_REG = PeripheralBase + $00215054; AUX_MU_MSR_REG = PeripheralBase + $00215058; AUX_MU_SCRATCH = PeripheralBase + $0021505C; AUX_MU_CNTL_REG = PeripheralBase + $00215060; AUX_MU_STAT_REG = PeripheralBase + $00215064; AUX_MU_BAUD_REG = PeripheralBase + $00215068; implementation {$IFDEF FPC_DOTTEDUNITS} uses EmbeddedApi.ConsoleIO; {$ELSE FPC_DOTTEDUNITS} uses consoleio; {$ENDIF FPC_DOTTEDUNITS} procedure _FPC_haltproc; assembler; nostackframe; public name '_haltproc'; asm .Lhalt: wfi b .Lhalt end; procedure DUMMY(Count: DWord); var i : DWord; begin for i := 0 to Count do begin asm nop end; end; end; procedure PUT32(Address: DWord; Value: DWord); inline; VAR p: ^DWord; begin p := POINTER (Address); p^ := Value; end; function GET32(Address: DWord) : DWord; inline; VAR p: ^DWord; begin p := POINTER (Address); GET32 := p^; end; function UARTLCR(): DWord; begin UARTLCR := GET32(AUX_MU_LCR_REG); end; procedure UARTPuts(C: AnsiChar); begin while True do begin if (GET32(AUX_MU_LSR_REG) and $20) > 0 then break; end; PUT32(AUX_MU_IO_REG, DWord(C)); end; function UARTGet(): AnsiChar; begin while True do begin if (GET32(AUX_MU_LSR_REG) and $01) > 0 then break; end; UARTGet := AnsiChar(GET32(AUX_MU_IO_REG) and $FF); end; procedure UARTFlush(); begin while True do begin if (GET32(AUX_MU_LSR_REG) and $100) > 0 then break; end; end; function RaspiWrite(ACh: AnsiChar; AUserData: pointer): boolean; begin UARTPuts(ACh); RaspiWrite := true; end; function RaspiRead(var ACh: AnsiChar; AUserData: pointer): boolean; begin if (GET32(AUX_MU_LSR_REG) and $01) > 0 then begin ACh := UARTGet(); end else begin ACh := #0; end; RaspiRead := true; end; procedure UARTInit; public name 'UARTInit'; var ra: dword; begin PUT32(AUX_ENABLES, 1); PUT32(AUX_MU_IER_REG, 0); PUT32(AUX_MU_CNTL_REG, 0); PUT32(AUX_MU_LCR_REG, 3); PUT32(AUX_MU_MCR_REG, 0); PUT32(AUX_MU_IER_REG, 0); PUT32(AUX_MU_IIR_REG, $C6); PUT32(AUX_MU_BAUD_REG, 270); ra := GET32(GPFSEL1); ra := ra AND (not (7 shl 12)); // gpio14 ra := ra OR (2 shl 12); // alt5 ra := ra AND (not (7 shl 15)); // gpio15 ra := ra OR (2 shl 15); // alt5 PUT32(GPFSEL1, ra); PUT32(GPPUD, 0); Dummy(500); PUT32(GPPUDCLK0, ((1 shl 14) OR (1 shl 15))); Dummy(500); PUT32(GPPUDCLK0, 0); PUT32(AUX_MU_CNTL_REG, 3); end; {$ifndef CUSTOM_ENTRY} procedure PASCALMAIN; external name 'PASCALMAIN'; var _stack_top: record end; external name '_stack_top'; { This start makes sure we only execute on core 0 - the others will halt } procedure _FPC_start; assembler; nostackframe; label _start; asm .init .align 16 .globl _start _start: // enable fpu .long 0xee110f50 // mrc p15, 0, r0, c1, c0, 2 orr r0, r0, #0x300000 // single precision orr r0, r0, #0xC00000 // double precision .long 0xee010f50 // mcr p15, 0, r0, c1, c0, 2 mov r0, #0x40000000 .long 0xeee80a10 // fmxr fpexc, r0 .long 0xee100fb0 // mrc p15,0,r0,c0,c0,5 - find the core ID mov r1, #0xFF ands r1, r1, r0 bne _FPC_haltproc ldr r0, .L_stack_top mov sp, r0 bl UARTInit bl PASCALMAIN bl _FPC_haltproc .L_stack_top: .long _stack_top .text end; {$endif CUSTOM_ENTRY} begin OpenIO(Input, @RaspiWrite, @RaspiRead, fmInput, nil); OpenIO(Output, @RaspiWrite, @RaspiRead, fmOutput, nil); OpenIO(ErrOutput, @RaspiWrite, @RaspiRead, fmOutput, nil); OpenIO(StdOut, @RaspiWrite, @RaspiRead, fmOutput, nil); OpenIO(StdErr, @RaspiWrite, @RaspiRead, fmOutput, nil); end.