Forum: Mikrocontroller und Digitale Elektronik Ursache für ARM9 "ABORT mode" finden


von Olli Z. (z80freak)


Lesenswert?

Ich habe hier ein Problem mit einem Radio auf dem ein OMAP-Prozessor 
(OMAP5912 derivat) verbaut ist. Der hat eine ARM9 CPU drauf, externen 
SDRAM und Flash. Ich kann per JTAG auf die CPU zugreifen und auch das 
Flash lesen/programmieren. Trotzdem bootet das Ding nicht weil irgendwas 
nicht stimmt. Ich habe bereits die Firmware neu geflasht (von einem 
laufenden Gerät), aber das hat nichts geändert. Es gibt wohl eine 
externe Abhängigkeit/defekt die ich noch nicht gefunden habe.

Beim Connect mit J-Link sehe ich das die CPU nach einem Reset immer hier 
hängen bleibt:
1
J-Link: ARM9 CP15 Settings changed: 5327F from 78, MMU On, ICache On, DCache On
2
PC: (R15) = FFFF000C, CPSR = 000000D7 (ABORT mode, ARM FIQ dis. IRQ dis.)
3
Current:
4
     R0 =00000003, R1 =9014D818, R2 =2C28D86C, R3 =00070F7C
5
     R4 =90000014, R5 =2000FE28, R6 =00000000, R7 =0000001C
6
     R8 =00000040, R9 =FFF6FACD, R10=3BFF97FE, R11=00040034, R12=00000000
7
     R13=BBE9D6AB, R14=00000002, SPSR=000000F7
8
USR: R8 =00000040, R9 =FFF6FACD, R10=3BFF97FE, R11=00040034, R12=00000000
9
     R13=4BDFFB35, R14=FE7B70FF
10
FIQ: R8 =F819FD75, R9 =EBCD07F7, R10=F9DFA3D6, R11=F7FFAFF7, R12=CE7FBED9
11
     R13=F3FBFD73, R14=67EEFFF1, SPSR=00000010
12
IRQ: R13=FEBED7DA, R14=F46E7BFE, SPSR=00000010
13
SVC: R13=2000FE18, R14=00001FA0, SPSR=00000010
14
ABT: R13=BBE9D6AB, R14=00000002, SPSR=000000F7
15
UND: R13=9FF77F7B, R14=BF7DFFD1, SPSR=00000010

0xFFFF000C ist der Reset-Vector vom ABORT Interrupt (soweit ich das 
weis). Und der "ABORT mode" zeigt es ja auch an.

War es nicht so das in einem solchen Fall R13 auf den Stacktrace zeigt 
und R14 auf die Adresse in der der Abbruch stattfand?
1
ABT: R13=BBE9D6AB, R14=00000002, SPSR=000000F7
Von der Adresse her wäre aber doch in R14 ein illegaler Wert mit 
0x0000_0002?

Die von R13 angezeigte Stack-Trace Adresse liegt im Bereich des externen 
SDRAMs (EMIFF), welcher von 0x8000_0000 bis 0xEFFF_FFFF geht. Wenn ich 
versuche über JTAG den Bereich zu lesen erhalte ich einen Fehler:
1
J-Link>mem 0xbbe9d6ab, 64
2
Could not read memory.

Aus dem internen SRAM kann ich aber lesen. Möglicherweise ist aber zum 
Zeitpunkt des ABORTs das externe SDRAM noch garnicht verfügbar, wodurch 
der Adressbereich noch nicht belegt ist?

Hat hier jemand genug Erfahrung mir da ein wenig unter die ARMe zu 
greifen? ;-) Ich würde gern herausfinden warum und wo der ABORT 
stattfindet. Evtl. gibt mir das Aufschluß darüber was mit der Hardware 
nicht stimmt?

Ein Abort kann ja auch durch Timeouts beim Zugriff auf externe 
Peripherie ausgelöst werden. Hier liegt meine Vermutung. Aber ohne einen 
Anhaltspunkt wo ist das stochern im Nebel. Natürlich habe ich schon die 
bekannten bzw. möglichen Fehlerquellen geprüft wie das RAM, das Flash, 
die Stromversorgungen, Power-Control und Boot-Control, aber alles ohne 
erkennbares Problem.

von Olli Z. (z80freak)



Lesenswert?

Normalerweise läuft das Programm ja im SVC mode (Supervisor). Irgendwann 
kommt dann das Problem und er wechselt in den ABORT mode. Ist dann nicht 
vom obigen regs der letzte ausgeführte Befehl hier zu suchen?
1
SVC: R13=2000FE18, R14=00001FA0, SPSR=00000010
Also an R14?

Hier mal der Disassembly aus diesem Bereich:
1
ROM:00001F7C                 PUSH    {R4,LR}
2
ROM:00001F80                 MOV     R4, R0
3
ROM:00001F84                 MOV     R0, R1
4
ROM:00001F88                 MOV     R1, R2
5
ROM:00001F8C                 MOV     R2, R3
6
ROM:00001F90                 LDR     R3, [SP,#8+arg_0]
7
ROM:00001F94                 ADD     R4, R4, #0x14
8
ROM:00001F98                 MOV     LR, PC
9
ROM:00001F9C                 BX      R4
10
ROM:00001FA0                 POP     {R4,PC}

Das habe ich mal mit einem Breakpoint ein paar Befehle davor geprüft:
1
J-Link>setbp 0x1f7c t
2
Breakpoint set @ addr 0x00001F7C (Handle = 1)
3
J-Link>setpc 0
4
J-Link>go
5
J-Link>s
6
00001F7C:   10 40 2D E9        PUSH    {R4,LR}
7
J-Link>s
8
00001F80:   00 40 A0 E1        MOV     R4, R0
9
J-Link>s
10
00001F84:   01 00 A0 E1        MOV     R0, R1
11
J-Link>s
12
00001F88:   02 10 A0 E1        MOV     R1, R2
13
J-Link>s
14
00001F8C:   03 20 A0 E1        MOV     R2, R3
15
J-Link>s
16
00001F90:   08 30 9D E5        LDR     R3, [SP, #+0x08]
17
J-Link>s
18
00001F94:   14 40 84 E2        ADD     R4, R4, #0x14
19
J-Link>s
20
00001F98:   0F E0 A0 E1        MOV     LR, PC
21
J-Link>s
22
00001F9C:   14 FF 2F E1        BX      R4
23
J-Link>s
24
90000014:   18 F0 1F E5        LDR     PC, [PC, #-0x18]    ; 0x90000034
25
J-Link>s
26
27
****** Error: Failed to read current instruction.
28
J-Link>regs
29
PC: (R15) = E51FF018, CPSR = 000000D3 (SVC mode, ARM FIQ dis. IRQ dis.)
30
Current:
31
     R0 =00000003, R1 =9014D818, R2 =2C28D86C, R3 =00070F7C
32
     R4 =90000014, R5 =2000FE28, R6 =00000000, R7 =0000001C
33
     R8 =00000040, R9 =FFF6FACD, R10=3BFF97FE, R11=00040034, R12=00000000
34
     R13=2000FE18, R14=00001FA0, SPSR=00000010
35
USR: R8 =00000040, R9 =FFF6FACD, R10=3BFF97FE, R11=00040034, R12=00000000
36
     R13=4BDFFB35, R14=FE7B70FF
37
FIQ: R8 =F819FD75, R9 =EBCD07F7, R10=F9DFA3D6, R11=F7FFAFF7, R12=CE7FBED9
38
     R13=F3FBFD73, R14=67EEFFF1, SPSR=00000010
39
IRQ: R13=FEBED7DA, R14=F46E7BFE, SPSR=00000010
40
SVC: R13=2000FE18, R14=00001FA0, SPSR=00000010
41
ABT: R13=BBE9D6AB, R14=00000002, SPSR=000000F7
42
UND: R13=9FF77F7B, R14=BF7DFFD1, SPSR=00000010

An 0x1F9C springt er ja mit einem call an die Adresse von R4, wo zu 
diesem Zeitpunkt 0x9000_0014 drin steht. Eine Zielmarke im SDRAM. Dort 
springt er wohl weiter nach 0x9000_0034. Die Adresse muss er ja aus dem 
Speicherort 0x9000_0014 - 0x18 = 0x8FFF_FFFC gelesen haben. Von der 
Zielmarke her (aligned) eher ein ARM als ein Thumb-Befehl?. Aber das 
scheint er dann nicht mehr hin zu bekommen (Fehlermeldung). Danach ist 
der PC auf 0xE51FF018 gestellt, warum auch immer?!

Den Speicher ab 0x9000_0000 kann ich übrigens problemlos auslesen:
1
J-Link>mem 0x90000000, 64
2
90000000 = 18 F0 1F E5 18 F0 1F E5  18 F0 1F E5 18 F0 1F E5  ................
3
90000010 = 18 F0 1F E5 18 F0 1F E5  18 F0 1F E5 18 F0 1F E5  ................
4
90000020 = 40 28 12 90 2C 2A 12 90  54 2A 12 90 7C 2C 12 90  @(..,*..T*..|,..
5
90000030 = 24 2C 12 90 4C 2B 12 90  1C 31 12 90 40 33 12 90  $,..L+...1..@3..
6
90000040 = 30 40 2D E9 43 DF 4D E2  04 00 0D E2 2F 54 05 FB  0@-.C.M...../T..
7
90000050 = 6D 1F 0F E2 04 00 0D E2  15 54 05 FA 00 40 30 E1  m........T...@0.
8
90000060 = 10 00 00 1A                                       ....

Einzig das bei mehreren gleichen Lesezyklen ab und zu mal ein anderer 
Inhalt erscheint, wenn auch immer derselbe:
1
J-Link>mem 0x90000000, 64
2
90000000 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
3
90000010 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
4
90000020 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
5
90000030 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
6
90000040 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
7
90000050 = 60 54 05 FA 01 1F 0F E2  60 54 05 FA 01 1F 0F E2  `T......`T......
8
90000060 = 60 54 05 FA                                       `T..

Da das im SDRAM ist, dürfte das doch bei einer angehaltenen CPU nicht 
sein, oder? Das müsste doch immer gleich sein...

Vom Rest des Codes her ist das in einem Bereich wo Images aus dem Flash 
ins RAM geladen werden. Was darin genau abgeht weiss ich noch nicht aber 
es wird ein Image nach dem anderen übertragen und dann ausgeführt 
(initialisiert). Und in einem davon scheint es dann zu knallen.

Ich schaue mal ob ich durch einen Breakpoint in der Verzeigungsroutine 
(case) herausbekomme bei welchem das der Fall ist.

Hier auch mal zur Vollständigkeit das Decompile dieses Bereichs:
1
int __fastcall sub_52(int a1, int a2, int *a3)
2
{
3
  int v4; // r1
4
  int result; // r0
5
  int v6; // r0
6
  unsigned int i; // r7
7
  int v8; // r4
8
  int v9; // r0
9
  int v10; // r6
10
  bool v11; // zf
11
  int v12; // r0
12
  int v13; // r5
13
  int v14; // r0
14
  unsigned int j; // r4
15
  int v16; // [sp+4h] [bp-D4h]
16
  int v17[39]; // [sp+8h] [bp-D0h] BYREF
17
  int v18; // [sp+A4h] [bp-34h]
18
  unsigned int v19; // [sp+A8h] [bp-30h]
19
  int v20; // [sp+ACh] [bp-2Ch]
20
  int v21; // [sp+B0h] [bp-28h]
21
  int v22; // [sp+B4h] [bp-24h]
22
  int v23; // [sp+B8h] [bp-20h]
23
  int v24; // [sp+BCh] [bp-1Ch]
24
  int *v25; // [sp+C0h] [bp-18h]
25
26
  v23 = a1;
27
  v24 = a2;
28
  v25 = a3;
29
  v20 = a1;
30
  v21 = 0;
31
  v18 = 0;
32
  sub_12AC(v17, 156);
33
  v4 = sub_4A4(v20);
34
  result = -1;
35
  if ( v4 == 1 && a2 != -1 )
36
  {
37
    v19 = sub_4F4(v20);
38
    if ( (sub_4F0(v20) & 2) != 0 )
39
    {
40
      v6 = sub_4EC(v20);
41
      *v25 = v6;
42
      v18 = 1;
43
    }
44
    for ( i = 0; i < v19; ++i )
45
    {
46
      v22 = (unsigned __int16)i;
47
      v8 = sub_572(v20);
48
      v11 = v8 == 0;
49
      while ( !v11 )
50
      {
51
        v9 = sub_5C4(v20, v22);
52
        v10 = v9 + v21;
53
        v11 = v9 + v21 == -1;
54
        if ( v9 + v21 != -1 )
55
        {
56
          v11 = v10 == 0;
57
          if ( v10 )
58
          {
59
            v12 = sub_51C(v20, v22);
60
            v11 = v12 == 0;
61
            if ( v12 )
62
            {
63
              v13 = sub_58C(v20, v22);
64
              v11 = v13 == 0;
65
              if ( v13 )
66
              {
67
                v16 = sub_4FC(v20, v22);
68
                if ( !v16 )
69
                  goto LABEL_47;
70
                if ( !sub_1370(v16, "DOE_SDRAM_RO", 12) )
71
                {
72
                  v17[2] = v8;
73
                  v17[1] = v13;
74
                  v17[0] = v10;
75
                  break;
76
                }
77
                if ( !sub_1370(v16, "DOE_SDRAM_RW", 12) )
78
                {
79
                  v17[5] = v8;
80
                  v17[4] = v13;
81
                  v17[3] = v10;
82
                  break;
83
                }
84
                if ( !sub_1370(v16, "DOE_SDRAM_ZI", 12) )
85
                {
86
                  v17[8] = v8;
87
                  v17[7] = v13;
88
                  v17[6] = v10;
89
                  break;
90
                }
91
                if ( !sub_1370(v16, "DSP_IMAGE_RO", 12) )
92
                {
93
                  v17[11] = v8;
94
                  v17[10] = v13;
95
                  v17[9] = v10;
96
                  break;
97
                }
98
                if ( !sub_1370(v16, "TESTCODE_RO", 11) )
99
                {
100
                  v17[14] = v8;
101
                  v17[13] = v13;
102
                  v17[12] = v10;
103
                  break;
104
                }
105
                if ( !sub_1370(v16, "TESTCODE_RW", 11) )
106
                {
107
                  v17[17] = v8;
108
                  v17[16] = v13;
109
                  v17[15] = v10;
110
                  break;
111
                }
112
                if ( !sub_1370(v16, "TESTCODE_ZI", 11) )
113
                {
114
                  v17[20] = v8;
115
                  v17[19] = v13;
116
                  v17[18] = v10;
117
                  break;
118
                }
119
                if ( !sub_1370(v16, "RADIOLIB_RO_V", 13) )
120
                {
121
                  v17[21] = -805306368;
122
                  v17[23] = v8;
123
                  v17[22] = v13;
124
                  break;
125
                }
126
                if ( !sub_1370(v16, "RADIOLIB_RW_V", 13) )
127
                {
128
                  v17[26] = v8;
129
                  v17[25] = v13;
130
                  v17[24] = -804782080;
131
                  break;
132
                }
133
                if ( !sub_1370(v16, "RADIOLIB_ZI_V", 13) )
134
                {
135
                  v17[29] = v8;
136
                  v17[28] = v13;
137
                  v17[27] = -804519936;
138
                  break;
139
                }
140
                if ( !sub_1370(v16, "RADIOLIB_RO_N", 13) )
141
                {
142
                  v17[30] = -805306368;
143
                  v17[32] = v8;
144
                  v17[31] = v13;
145
                  break;
146
                }
147
                if ( !sub_1370(v16, "RADIOLIB_RW_N", 13) )
148
                {
149
                  v17[35] = v8;
150
                  v17[34] = v13;
151
                  v17[33] = -804782080;
152
                  break;
153
                }
154
                if ( !sub_1370(v16, "RADIOLIB_ZI_N", 13) )
155
                {
156
                  v17[38] = v8;
157
                  v17[37] = v13;
158
                  v17[36] = -804519936;
159
                  break;
160
                }
161
                if ( sub_1370(v16, "RAMDISK_NOINIT", 14)
162
                  && sub_1370(v16, "PADDING", 7)
163
                  && sub_1370(v16, "SDRAM_STACK", 11)
164
                  && sub_1370(v16, "CC_DSP_SHARED", 13)
165
                  && sub_1370(v16, "DD_DSP_SHARED", 13)
166
                  && sub_1370(v16, "HH_DSP_SHARED", 13) )
167
                {
168
LABEL_47:
169
                  v14 = sub_51C(v20, v22);
170
                  if ( v14 == 1 || v14 == 2 || v14 != 3 && v14 == 4 )
171
                    sub_211C(v13, v10, v8);
172
                }
173
                break;
174
              }
175
            }
176
          }
177
        }
178
      }
179
    }
180
    for ( j = 0; j < 0xD; ++j )
181
      sub_1F7C(*v25, j + 3, v17[3 * j], v17[3 * j + 1], v17[3 * j + 2]);
182
    result = v18;
183
  }
184
  return result;
185
}

: Bearbeitet durch User
von Olli Z. (z80freak)


Lesenswert?

Ich glaube ich liege total falsch, diese Kaskade da oben scheint eher 
ein Teil des Bootloaders zu sein. Hier wird im Kern ein String-Vergleich 
durchgeführt. Und zwar gibt es im SRAM eine Adresse (z.B. 0x2C5EB7A5) 
welche durch die ganze Kette durchgeschleust und nach einem String-Match 
gesucht wird. An besagtem SRAM steht da:
1
2C5EB7A5 = 53 44 52 41 4D 5F 49 4E  49 54 00 53 44 52 41 4D  SDRAM_INIT.SDRAM
2
2C5EB7B5 = 5F 52 4F 00 50 41 44 44  49 4E 47 31 00 44 4F 45  _RO.PADDING1.DOE
3
2C5EB7C5 = 5F 53 44 52 41 4D 5F 52  4F 00 50 41 44 44 49 4E  _SDRAM_RO.PADDIN
4
2C5EB7D5 = 47 32 00 53 44 52 41 4D  5F 52 57 00 53 44 52 41  G2.SDRAM_RW.SDRA
5
2C5EB7E5 = 4D 5F 5A 49 00 52 41 4D  44 49 53 4B 5F 4E 4F 49  M_ZI.RAMDISK_NOI
6
2C5EB7F5 = 4E 49 54 00 44 4F 45 5F  53 44 52 41 4D 5F 52 57  NIT.DOE_SDRAM_RW
7
2C5EB805 = 00 44 4F 45 5F 53 44 52  41 4D 5F 5A 49 00 53 44  .DOE_SDRAM_ZI.SD
8
2C5EB815 = 52 41 4D 5F 53 54 41 43  4B 5F 5A 49 00 44 53 50  RAM_STACK_ZI.DSP
9
2C5EB825 = 5F 49 4D 41 47 45 5F 52  4F 00 54 45 53 54 43 4F  _IMAGE_RO.TESTCO
10
2C5EB835 = 44 45 5F 52 4F 00 50 41  44 44 49 4E 47 5F 54 45  DE_RO.PADDING_TE
11
2C5EB845 = 53 54 43 4F 44 45 00 54  45 53 54 43 4F 44 45 5F  STCODE.TESTCODE_
12
2C5EB855 = 52 57 00 54 45 53 54 43  4F 44 45 5F 5A 49 00 42  RW.TESTCODE_ZI.B
13
2C5EB865 = 42 5F 44 53 50 5F 5A 43  4C 44 5F 5A 49 00 43 43  B_DSP_ZCLD_ZI.CC
14
2C5EB875 = 5F 44 53 50 5F 53 48 41  52 45 44 5F 50 4F 4F 4C  _DSP_SHARED_POOL
15
2C5EB885 = 00 44 44 5F 44 53 50 5F  53 48 41 52 45 44 5F 53  .DD_DSP_SHARED_S
16
2C5EB895 = 45 4D 4C 49 53 54 00 46  46 5F 44 53 50 5F 53 48  EMLIST.FF_DSP_SH
17
2C5EB8A5 = 41 52 45 44 5F 5A 43 4C  44 5F 49 4E 49 54 5F 44  ARED_ZCLD_INIT_D
18
2C5EB8B5 = 4F 4E 45 00 47 47 5F 44  53 50 5F 53 48 41 52 45  ONE.GG_DSP_SHARE
19
2C5EB8C5 = 44 5F 50 4F 4F 4C 44 41  54 41 00 48 48 5F 44 53  D_POOLDATA.HH_DS
20
2C5EB8D5 = 50 5F 53 48 41 52 45 44  5F 53 50 45 45 43 48 52  P_SHARED_SPEECHR
21
2C5EB8E5 = 45 43 4F 00 50 4F 57 45  52 5F 4D 4F 44 45 00 49  ECO.POWER_MODE.I
22
2C5EB8F5 = 44 4C 45 5F 45 4E 54 52  59 00 2E 6E 6F 74 65 00  DLE_ENTRY..note.
23
2C5EB905 = 2E 63 6F 6D 6D 65 6E 74  00 2E 73 68 73 74 72 74  .comment..shstrt
24
2C5EB915 = 61 62 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ab..............

Nun wird nacheinander verglichen ob der String an der Position im SRAM 
mit einem der fixen Strings in der Switch/Case übereinstimmt.

Interessant ist, das es in diesem SRAM-Bereich zwar ein "SDRAM_INIT" 
gibt, dieses in der großen Switch/Case aber nicht vorkommt. Hmm...

: Bearbeitet durch User
von Johannes K. (krotti42)


Lesenswert?

Hallo!

Ich würde mal versuchen die Register ESR_EL3 (Exception Syndrome 
Register) und FAR_EL3 (Fault Address Register) auszulesen, wenn mit 
J-Link möglich. Solltest du das noch nicht gemacht haben. Bei FAR_ELx 
"sollte" die tatsächliche Adresse hinterlegt sein, wo der Fehler 
aufgetreten ist. ESR_ELx "sollte" angeben, was der Fehler genau war.

Exception Syndrome Register:
https://developer.arm.com/documentation/ddi0595/2020-12/AArch64-Registers/ESR-EL3--Exception-Syndrome-Register--EL3-

von Dieter S. (ds1)


Lesenswert?

Johannes K. schrieb:
>
> Ich würde mal versuchen die Register ESR_EL3 (Exception Syndrome
> Register) und FAR_EL3 (Fault Address Register) auszulesen, wenn mit
> J-Link möglich.

Ab welcher ARM Generation gibt es die denn? Ich befürchte dass der ARM9 
(also Generation ARMv4 oder ARMv5 von ca. 2002) des TO diese noch nicht 
hat.

von Johannes K. (krotti42)


Lesenswert?

Dieter S. schrieb:
> Johannes K. schrieb:
>>
>> Ich würde mal versuchen die Register ESR_EL3 (Exception Syndrome
>> Register) und FAR_EL3 (Fault Address Register) auszulesen, wenn mit
>> J-Link möglich.
>
> Ab welcher ARM Generation gibt es die denn? Ich befürchte dass der ARM9
> (also Generation ARMv4 oder ARMv5 von ca. 2002) des TO diese noch nicht
> hat.

Ab ARMv8... Dachte an ARMv9. ARMv9 != ARM9

Sorry, mein Fehler.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.