Преглед изворни кода

+ patch by Jeppe Johansen to support automatic interrupt table generation by using the interrupt directive with an offset. Not activated yet because it requires to change also the startup code of the different mcus.

git-svn-id: trunk@17279 -
florian пре 14 година
родитељ
комит
3ce9ff93f1

+ 16 - 1
compiler/arm/cpuinfo.pas

@@ -99,7 +99,9 @@ Const
      pocall_softfloat,
      { same as stdcall (requires that all const records are passed by
        reference, but that's already done for stdcall) }
-     pocall_mwpascal
+     pocall_mwpascal,
+     { used for interrupt handling }
+     pocall_interrupt
    ];
 
    cputypestr : array[tcputype] of string[8] = ('',
@@ -147,6 +149,19 @@ Const
       'STELLARIS'
      );
 
+   interruptvectors : array[tcontrollertype] of longint =
+     (0,
+      8,
+      8,
+      8,
+      8,
+      8,
+      8,
+      8,
+      12+59, { XL-density }
+      12 { No model specified }
+     );
+
    vfp_scalar = [fpu_vfpv2,fpu_vfpv3];
 
    { Supported optimizations, only used for information }

+ 2 - 1
compiler/globals.pas

@@ -1007,7 +1007,8 @@ implementation
          'SAFECALL',
          'STDCALL',
          'SOFTFLOAT',
-         'MWPASCAL'
+         'MWPASCAL',
+         'INTERRUPT'
         );
       var
         t  : tproccalloption;

+ 5 - 2
compiler/globtype.pas

@@ -360,7 +360,9 @@ interface
          pocall_softfloat,
          { Metrowerks Pascal. Special case on Mac OS (X): passes all }
          { constant records by reference.                            }
-         pocall_mwpascal
+         pocall_mwpascal,
+         { Special interrupt handler for embedded systems }
+         pocall_interrupt
        );
        tproccalloptions = set of tproccalloption;
 
@@ -377,7 +379,8 @@ interface
            'SafeCall',
            'StdCall',
            'SoftFloat',
-           'MWPascal'
+           'MWPascal',
+           'Interrupt'
          );
 
        { Default calling convention }

+ 2 - 1
compiler/ncgrtti.pas

@@ -636,7 +636,8 @@ implementation
               { pocall_safecall   } 4,
               { pocall_stdcall    } 3,
               { pocall_softfloat  } 10,
-              { pocall_mwpascal   } 11
+              { pocall_mwpascal   } 11,
+              { pocall_interrupt  } 12
              );
 
            procedure write_para(parasym:tparavarsym);

+ 13 - 0
compiler/pdecsub.pas

@@ -1611,9 +1611,22 @@ begin
 end;
 
 procedure pd_interrupt(pd:tabstractprocdef);
+
+var v: Tconstexprint;
+
 begin
   if pd.parast.symtablelevel>normal_function_level then
     Message(parser_e_dont_nest_interrupt);
+
+  if target_info.system in systems_interrupt_table then
+    begin
+      if token<>_SEMICOLON then
+        begin
+          pd.proccalloption:=pocall_interrupt;
+          v:=get_intconst;
+          Tprocdef(pd).interruptvector:=v.uvalue;
+        end;
+    end;
 end;
 
 procedure pd_abstract(pd:tabstractprocdef);

+ 88 - 2
compiler/pmodules.pas

@@ -49,10 +49,10 @@ implementation
        wpobase,
        scanner,pbase,pexpr,psystem,psub,pdecsub,ptype
        ,cpuinfo
-{$ifdef i386}
+{$if defined(i386) or defined(ARM)}
        { fix me! }
        ,cpubase
-{$endif i386}
+{$endif defined(i386) or defined(ARM)}
        ;
 
 
@@ -472,6 +472,89 @@ implementation
       end;
 
 
+    procedure InsertInterruptTable;
+
+      procedure WriteVector(const name: string);
+        var
+          ai: taicpu;
+        begin
+{$IFDEF arm}
+          if current_settings.cputype in [cpu_armv7m, cpu_cortexm3] then
+            current_asmdata.asmlists[al_globals].concat(tai_const.Createname(name,0))
+          else
+            begin
+              ai:=taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(name));
+              ai.is_jmp:=true;
+              current_asmdata.asmlists[al_globals].concat(ai);
+            end;
+{$ENDIF arm}
+        end;
+
+      function GetInterruptTableLength: longint;
+        begin
+{$if defined(ARM)}
+          result:=interruptvectors[current_settings.controllertype];
+{$else}
+          result:=0;
+{$endif}
+        end;
+
+      var
+        hp: tused_unit;
+        sym: tsym;
+        i, i2: longint;
+        interruptTable: array of tprocdef;
+        pd: tprocdef;
+      begin
+        SetLength(interruptTable, GetInterruptTableLength);
+        FillChar(interruptTable[0], length(interruptTable)*sizeof(pointer), 0);
+
+        hp:=tused_unit(usedunits.first);
+        while assigned(hp) do
+          begin
+            for i := 0 to hp.u.symlist.Count-1 do
+              begin
+                sym:=tsym(hp.u.symlist[i]);
+                if not assigned(sym) then
+                  continue;
+                if sym.typ = procsym then
+                  begin
+                    for i2 := 0 to tprocsym(sym).ProcdefList.Count-1 do
+                      begin
+                        pd:=tprocdef(tprocsym(sym).ProcdefList[i2]);
+                        if pd.interruptvector >= 0 then
+                          begin
+                            if pd.interruptvector > high(interruptTable) then
+                              Internalerror(2011030602);
+                            if interruptTable[pd.interruptvector] <> nil then
+                              internalerror(2011030601);
+
+                            interruptTable[pd.interruptvector]:=pd;
+                            break;
+                          end;
+                      end;
+                  end;
+              end;
+            hp:=tused_unit(hp.next);
+          end;
+
+        new_section(current_asmdata.asmlists[al_globals],sec_init,'VECTORS',sizeof(pint));
+        current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('VECTORS',AT_DATA,0));
+{$IFDEF arm}
+        if current_settings.cputype in [cpu_armv7m, cpu_cortexm3] then
+          current_asmdata.asmlists[al_globals].concat(tai_const.Createname('_stack_top',0)); { ARMv7-M processors have the initial stack value at address 0 }
+{$ENDIF arm}
+
+        for i:=0 to high(interruptTable) do
+          begin
+            if interruptTable[i]<>nil then
+              writeVector(interruptTable[i].mangledname)
+            else
+              writeVector('DefaultHandler'); { Default handler name }
+          end;
+      end;
+
+
     procedure InsertMemorySizes;
 {$IFDEF POWERPC}
       var
@@ -2363,6 +2446,9 @@ implementation
          InsertWideInitsTablesTable;
          InsertMemorySizes;
 
+         if target_info.system in systems_interrupt_table then
+           InsertInterruptTable;
+
          { Insert symbol to resource info }
          InsertResourceInfo(resources_used);
 

+ 7 - 0
compiler/symdef.pas

@@ -551,6 +551,8 @@ interface
           interfacedef : boolean;
           { true if the procedure has a forward declaration }
           hasforward  : boolean;
+          { interrupt vector }
+          interruptvector : longint;
           constructor create(level:byte);
           constructor ppuload(ppufile:tcompilerppufile);
           destructor  destroy;override;
@@ -3331,6 +3333,7 @@ implementation
 {$ifdef i386}
           fpu_used:=maxfpuregs;
 {$endif i386}
+         interruptvector:=-1;
       end;
 
 
@@ -3369,6 +3372,8 @@ implementation
          else
            import_name:=nil;
          import_nr:=ppufile.getword;
+         if target_info.system in systems_interrupt_table then
+           interruptvector:=ppufile.getlongint;
          if (po_msgint in procoptions) then
            messageinf.i:=ppufile.getlongint;
          if (po_msgstr in procoptions) then
@@ -3505,6 +3510,8 @@ implementation
          if po_has_importname in procoptions then
            ppufile.putstring(import_name^);
          ppufile.putword(import_nr);
+         if target_info.system in systems_interrupt_table then
+           ppufile.putlongint(interruptvector);
          if (po_msgint in procoptions) then
            ppufile.putlongint(messageinf.i);
          if (po_msgstr in procoptions) then

+ 2 - 0
compiler/systems.pas

@@ -449,6 +449,8 @@ interface
 
        systems_internal_sysinit = [system_i386_linux,system_i386_win32];
 
+       systems_interrupt_table = [{system_arm_embedded}];
+
        { all symbian systems }
        systems_symbian = [system_i386_symbian,system_arm_symbian];
 

+ 1 - 1
compiler/systems/t_embed.pas

@@ -267,7 +267,7 @@ begin
       Add('{');
       Add('     .text :');
       Add('    {');
-      Add('    *(.init, .init.*)');
+      Add('    KEEP(*(.init, .init.*))');
       Add('    *(.text, .text.*)');
       Add('    *(.strings)');
       Add('    *(.rodata, .rodata.*)');