View Issue Details

IDProjectCategoryView StatusLast Update
0035236FPCRTLpublic2020-01-23 22:15
ReporterRobert RolandAssigned ToFlorian 
PrioritynormalSeverityminorReproducibilityN/A
Status resolvedResolutionfixed 
Product Version3.3.1Product Build 
Target VersionFixed in Version3.3.1 
Summary0035236: Add a Raspberry Pi 2 ARM embedded target
DescriptionAttaching a patch that will add a Raspberry Pi 2 target to the ARM embedded RTL.

This does the following:

* sets up the FPU
* sets up UART1 (mini-UART) and attaches IO so Write/Read can be used
* executes PASCALMAIN on core 0 only - the other 3 cores halt
TagsNo tags attached.
Fixed in Revision44027
FPCOldBugId
FPCTarget-
Attached Files
  • 01-raspi2-take-2.patch (7,200 bytes)
    Index: compiler/arm/cpuinfo.pas
    ===================================================================
    --- compiler/arm/cpuinfo.pas	(revision 41664)
    +++ compiler/arm/cpuinfo.pas	(working copy)
    @@ -479,6 +479,9 @@
           ct_nrf52832_xxaa,
           ct_nrf52840_xxaa,
     
    +      { Raspberry Pi 2 }
    +      ct_raspi2,
    +
           // generic Thumb2 target
           ct_thumb2bare
          );
    @@ -993,6 +996,9 @@
           (controllertypestr:'NRF52832_XXAA'; controllerunitstr:'NRF52'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
           (controllertypestr:'NRF52840_XXAA'; controllerunitstr:'NRF52'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
           
    +      { Raspberry Pi 2 }
    +      (controllertypestr:'RASPI2'; controllerunitstr:'RASPI2'; cputype:cpu_armv7a; fputype:fpu_vfpv4; flashbase:$00000000; flashsize:$00000000; srambase:$00008000; sramsize:$10000000),
    +
           { Bare bones }
           (controllertypestr:'THUMB2_BARE';	controllerunitstr:'THUMB2_BARE';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$20000000;	sramsize:$00000400)
         );
    Index: compiler/systems/t_embed.pas
    ===================================================================
    --- compiler/systems/t_embed.pas	(revision 41664)
    +++ compiler/systems/t_embed.pas	(working copy)
    @@ -618,6 +618,10 @@
           ct_nrf52840_xxaa,
           
           ct_sc32442b,
    +
    +      { Raspberry Pi 2 }
    +      ct_raspi2,
    +
           ct_thumb2bare:
             begin
              with embedded_controllers[current_settings.controllertype] do
    Index: rtl/embedded/Makefile
    ===================================================================
    --- rtl/embedded/Makefile	(revision 41664)
    +++ rtl/embedded/Makefile	(working copy)
    @@ -376,7 +376,7 @@
     CPU_UNITS_DEFINED=1
     endif
     ifeq ($(SUBARCH),armv7a)
    -CPU_UNITS=allwinner_a20
    +CPU_UNITS=allwinner_a20 raspi2
     CPU_UNITS_DEFINED=1
     endif
     ifeq ($(CPU_UNITS_DEFINED),)
    Index: rtl/embedded/Makefile.fpc
    ===================================================================
    --- rtl/embedded/Makefile.fpc	(revision 41664)
    +++ rtl/embedded/Makefile.fpc	(working copy)
    @@ -91,7 +91,7 @@
     CPU_UNITS_DEFINED=1
     endif
     ifeq ($(SUBARCH),armv7a)
    -CPU_UNITS=allwinner_a20
    +CPU_UNITS=allwinner_a20 raspi2
     CPU_UNITS_DEFINED=1
     endif
     ifeq ($(CPU_UNITS_DEFINED),)
    Index: rtl/embedded/arm/raspi2.pp
    ===================================================================
    --- rtl/embedded/arm/raspi2.pp	(nonexistent)
    +++ rtl/embedded/arm/raspi2.pp	(working copy)
    @@ -0,0 +1,204 @@
    +unit raspi2;
    +
    +{$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
    +
    +uses
    +    consoleio;
    +
    +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: Char);
    +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(): Char;
    +begin
    +    while True do
    +    begin
    +        if (GET32(AUX_MU_LSR_REG) and $01) > 0 then break;
    +    end;
    +
    +    UARTGet := Char(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: char; AUserData: pointer): boolean;
    +begin
    +    UARTPuts(ACh);
    +
    +    RaspiWrite := true;
    +end;
    +
    +function RaspiRead(var ACh: char; 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.
    \ No newline at end of file
    
    01-raspi2-take-2.patch (7,200 bytes)

Activities

Robert Roland

2019-03-16 04:59

reporter   ~0114856

The MRC instruction doesn't like byte values as operands, so you'll see them in there as the actual opcodes. It looks to be an issue with armins.dat expected immshifter values. I'm not familiar enough with that code to submit a patch there.

The FMXR instruction will not be assembled by arm-eabi-as unless VFP is passed as an arg (which required building fpc with CROSSOPT=-CfVFPV4) but the CPU can execute the instruction fine.

Florian

2019-03-16 10:29

administrator   ~0114861

It seems the raspi2 unit itself is missing?

Robert Roland

2019-03-16 22:49

reporter  

01-raspi2-take-2.patch (7,200 bytes)
Index: compiler/arm/cpuinfo.pas
===================================================================
--- compiler/arm/cpuinfo.pas	(revision 41664)
+++ compiler/arm/cpuinfo.pas	(working copy)
@@ -479,6 +479,9 @@
       ct_nrf52832_xxaa,
       ct_nrf52840_xxaa,
 
+      { Raspberry Pi 2 }
+      ct_raspi2,
+
       // generic Thumb2 target
       ct_thumb2bare
      );
@@ -993,6 +996,9 @@
       (controllertypestr:'NRF52832_XXAA'; controllerunitstr:'NRF52'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
       (controllertypestr:'NRF52840_XXAA'; controllerunitstr:'NRF52'; cputype:cpu_armv7em; fputype:fpu_soft; flashbase:$00000000; flashsize:$00080000; srambase:$20000000; sramsize:$00010000),
       
+      { Raspberry Pi 2 }
+      (controllertypestr:'RASPI2'; controllerunitstr:'RASPI2'; cputype:cpu_armv7a; fputype:fpu_vfpv4; flashbase:$00000000; flashsize:$00000000; srambase:$00008000; sramsize:$10000000),
+
       { Bare bones }
       (controllertypestr:'THUMB2_BARE';	controllerunitstr:'THUMB2_BARE';	cputype:cpu_armv7m; fputype:fpu_soft; flashbase:$00000000;	flashsize:$00002000;	srambase:$20000000;	sramsize:$00000400)
     );
Index: compiler/systems/t_embed.pas
===================================================================
--- compiler/systems/t_embed.pas	(revision 41664)
+++ compiler/systems/t_embed.pas	(working copy)
@@ -618,6 +618,10 @@
       ct_nrf52840_xxaa,
       
       ct_sc32442b,
+
+      { Raspberry Pi 2 }
+      ct_raspi2,
+
       ct_thumb2bare:
         begin
          with embedded_controllers[current_settings.controllertype] do
Index: rtl/embedded/Makefile
===================================================================
--- rtl/embedded/Makefile	(revision 41664)
+++ rtl/embedded/Makefile	(working copy)
@@ -376,7 +376,7 @@
 CPU_UNITS_DEFINED=1
 endif
 ifeq ($(SUBARCH),armv7a)
-CPU_UNITS=allwinner_a20
+CPU_UNITS=allwinner_a20 raspi2
 CPU_UNITS_DEFINED=1
 endif
 ifeq ($(CPU_UNITS_DEFINED),)
Index: rtl/embedded/Makefile.fpc
===================================================================
--- rtl/embedded/Makefile.fpc	(revision 41664)
+++ rtl/embedded/Makefile.fpc	(working copy)
@@ -91,7 +91,7 @@
 CPU_UNITS_DEFINED=1
 endif
 ifeq ($(SUBARCH),armv7a)
-CPU_UNITS=allwinner_a20
+CPU_UNITS=allwinner_a20 raspi2
 CPU_UNITS_DEFINED=1
 endif
 ifeq ($(CPU_UNITS_DEFINED),)
Index: rtl/embedded/arm/raspi2.pp
===================================================================
--- rtl/embedded/arm/raspi2.pp	(nonexistent)
+++ rtl/embedded/arm/raspi2.pp	(working copy)
@@ -0,0 +1,204 @@
+unit raspi2;
+
+{$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
+
+uses
+    consoleio;
+
+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: Char);
+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(): Char;
+begin
+    while True do
+    begin
+        if (GET32(AUX_MU_LSR_REG) and $01) > 0 then break;
+    end;
+
+    UARTGet := Char(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: char; AUserData: pointer): boolean;
+begin
+    UARTPuts(ACh);
+
+    RaspiWrite := true;
+end;
+
+function RaspiRead(var ACh: char; 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.
\ No newline at end of file
01-raspi2-take-2.patch (7,200 bytes)

Robert Roland

2019-03-16 22:49

reporter   ~0114881

So sorry!! I forgot to svn add before I did an svn diff. See the 01-raspi2-take-2.patch

Issue History

Date Modified Username Field Change
2019-03-16 04:57 Robert Roland New Issue
2019-03-16 04:57 Robert Roland File Added: 01-raspi2.patch
2019-03-16 04:59 Robert Roland Note Added: 0114856
2019-03-16 10:29 Florian Note Added: 0114861
2019-03-16 22:49 Robert Roland File Added: 01-raspi2-take-2.patch
2019-03-16 22:49 Robert Roland Note Added: 0114881
2019-03-16 22:56 J. Gareth Moreton File Deleted: 01-raspi2.patch
2020-01-23 22:15 Florian Assigned To => Florian
2020-01-23 22:15 Florian Status new => resolved
2020-01-23 22:15 Florian Resolution open => fixed
2020-01-23 22:15 Florian Fixed in Version => 3.3.1
2020-01-23 22:15 Florian Fixed in Revision => 44027
2020-01-23 22:15 Florian FPCTarget => -