org 0xA0900000 code32 start DB SIEMENS_BOOTCODE DW 0x00000003 DW 11520

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
org 0xA0900000
code32
b start
DB "SIEMENS_BOOTCODE"
DW 0x00000003
DW 115200
DW 0, 0, 0, 0 ; тут, по-идее, boot key должен быть
start:
ADR SP, start
MRS R0, CPSR
BIC R0, R0, #0xFF ; &= ~11111111
ORR R0, R0, #0xC0 ; |= 11000000
MSR CPSR_c, R0
; adr SP, start
;
; mrs r1, cpsr ;/* R1 = CPSR */
; bic r1, r1, #0x1F ;/* R1 &= ~0x1F (11111) */
; orr r1, r1, #0xD3 ;/* R1 |= 0xD3 (11010011) */
; msr cpsr_cf, r1 ;/* CPSR = R1 */
; /* R0 = 0x50078 F B 7 3 */
; mov r0, 0x00050000
; add r0, r0, 0x78
; mcr p15, 0, r0, c1, c0 ; /* Sets MMU to (0101 0000 0000 0111 1000) */
; Enable write to einit-protected registers
mov r0, #0
bl set_einit
; Disable first watchdog
bl disable_fist_watchdog
; Disable write to einit-protected registers
mov r0, #1
bl set_einit
; Init watchdog
bl init_watchdog
; Установим скорость по умолчанию (115200)
mov r0, #1
bl uart_set_speed
; Сразу шлём ответ на пинг
b cmd_ping
main_loop:
; Читаем команду
bl uart_rx_byte
cmp r0, #0x51 ; 'Q' - Выход
beq cmd_quit
cmp r0, #0x45 ; 'E' - Приём и запуск бинарника
beq cmd_exec_bin
cmp r0, #0x2E ; '.' - keep alive
beq cmd_keep_alive
cmp r0, #0x41 ; 'A' - ping
beq cmd_ping
cmp r0, #0x53 ; 'S' - Установить скорость
beq cmd_set_speed
; bl serve_watchdog ; Сбросим ватчдог
b main_loop
; Fast power-off
cmd_quit:
bl switch_watchdog
bl switch_watchdog
q_l: b q_l
; Задать скорость
cmd_set_speed:
bl uart_rx_byte ; Принимаем номер скорости
bl uart_set_speed ; Задаём скорость
b main_loop ; Возвращаемся в main_loop
; Пинг
cmd_ping:
mov r0, #0x4f ; 'O'
bl uart_tx_byte ; Шлём ответ на пинг
b main_loop
; Keep alive
cmd_keep_alive:
bl serve_watchdog
b main_loop
; Приём и запуск бинарника
cmd_exec_bin:
; r0 - Текущий принятый байт
; r6 - вычисляемая чексумма бинарника (XOR)
; r7 - Размер бинарника
; r8 - Адрес следующего байта для записи в раме
; r9 - Адрес в раме, куда пишется наш бинарник
mov r0, 0xDE
mov r1, 0xA8000000
;add r1, r1, 0x00100000
strb r0, [r1]
;sub r1, r1, #1
;ldrb r0, [r1], #1
bl serve_watchdog
bl serve_watchdog
bl serve_watchdog
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
b cmd_quit
bl uart_rx_word ; Принимаем размер
mov r7, r0 ; Запишем размер в r2
mov r9, #0xA8000000 ; Адрес в раме, куда будем писать бинарник
mov r8, r9 ; Запишем начальный адрес байта для записи в r3
; Принимаем бинарник
bl serve_watchdog ; Watchdog
cmd_exec_bin_receiver_loop:
bl uart_rx_byte ; Принимаем байт
strb r0, [r8], #1 ; Запишем байт в память
SUB r8, r8, #1
bl serve_watchdog ; Watchdog
ldrb r0, [r8], #1
eor r6, r6, r0 ; Посчитаем контрольную сумму. r1 = r1 ^ r0
bl serve_watchdog ; Watchdog
subs r7, r7, #1 ; Отнимем 1 от размера
bne cmd_exec_bin_receiver_loop ; Продолжаем цикл до тех пор, пока не примем всё (size = 0)
bl serve_watchdog ; Watchdog
bl uart_rx_byte ; Примем контрольную сумму
cmp r0, r6 ; Проверим чексумму
beq cmd_exec_bin_success
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
mov r0, #0x45 ; 'E'
bl uart_tx_byte ; Отправим сообщение об ошибке
bl serve_watchdog ; Сбросим watchdog
b cmd_quit ; Вернёмся в main_loop
; Если успешно приняли и чексумма сошлась (o_O)
cmd_exec_bin_success:
mov r0, #0x4f ; 'O'
bl uart_tx_byte ; Отправим сообщение об успешной записи
bl serve_watchdog ; Сбросим watchdog
blx r9 ; Пробуем запустить принятый код..
mov r0, #0x4f ; 'O'
bl uart_tx_byte ; Отправим сообщение об успешной записи
; Сюда никогда не дойдёт.. наверное
b cmd_quit
; --------------------------------------------------
; Watchdog
; --------------------------------------------------
; void disable_fist_watchdog()
disable_fist_watchdog:
add r1, pc, WATCH_DOG-$-8
ldr r1, [r1]
ldr r0, [r1, #0x7C] ; SCU_ROMAMCR
bic r0, r0, #1
str r0, [r1, #0x7C] ; SCU_ROMAMCR
mov r0, #8
str r0, [r1, #0x28] ; SCU_ROMAMCR
bx lr
; -------------------------
; void set_einit(r0=on/off)
; uses r0, r1, r2, r3
set_einit:
add r3, pc, WATCH_DOG-$-8
ldr r3, [r3]
ldr r1, [r3, #0x24] ; SCU_WDTCON0
bic r1, r1, #0x0e
orr r1, r1, #0xf0
ldr r2, [r3, #0x28] ; SCU_WDTCON1
and r2, r2, #0x0c
orr r1, r1, r2
str r1, [r3, #0x24] ; SCU_WDTCON0
bic r1, r1, #0x0d
orr r1, r1, #2
orr r0, r0, r1
str r0, [r3, #0x24] ; SCU_WDTCON0
bx lr
; -------------------------
; void init_watchdog()
; uses r0, r1, r2, r3, r4
init_watchdog:
add r0, pc, WATCH_DOG-$-8
ldr r0, [r0]
LDR R0, [R0, #0x60] ; SCU_CHIPID
MOV R0, R0, LSR#8
AND R0, R0, #0xff
add r1, pc, PCL_62-$-8 ; PCL_62
ldr r1, [r1]
sub r2, r1, #0xcc
cmp r0, #0x14
bne iwd_1a
add r1, r1, #0x60
add r2, r2, #0x04
iwd_1a:
add r3, r2, #0x4
sub r4, r3, #0x0c
mov r12, r1
MOV R0, #1
STR R0, [R2]
MOV R0, #0x10
STR R0, [R3]
MOV R0, #0x500
STR R0, [R1]
MOV R0, #0x4000
ORR R0, R0, #0x510
STR R0, [R4]
add r1, pc, STM_4-$-8 ; STM_4
ldr r1, [r1]
LDR r11, [R1]
b switch_watchdog
; -------------------------
; void serve_watchdog()
; uses r0, r1, r2
serve_watchdog:
; read timer
add r2, pc, STM_4-$-8 ; STM_4
ldr r2, [r2]
ldr r0, [r2]
sub r1, r0, r11
cmp r1, #0x200
bcc swd_exit
; Save timer value
mov r11, r0
; ------------------------
; void switch_watchdog()
; uses r0, r1, r2
switch_watchdog:
LDR R0, [R12]
MOV R0, R0,LSL#22
LDR R2, [R12]
MVN R0, R0,LSR#31
BIC R2, R2, #0x200
AND R0, R0, #1
ORR R0, R2, R0,LSL#9
STR R0, [R12]
swd_exit:
BX LR
; --------------------------------------------------
; USART
; --------------------------------------------------
; set_usart_speed(r0)
; 0=57600, 1=115200, 2=230400, 3=460800, 4=614400, 5=921600, 6=1228800, 7=1600000
uart_set_speed:
adr r1, usart_speeds
ldr r1, [r1, r0, LSL#2]
mov r2, #0xf1000000 ; USART0_CLC
mov r0, r1, LSR#16
str r0, [r2, #0x14] ; USART0_BG
mov r0, r1, LSL#16
mov r0, r0, LSR#16
str r0, [r2, #0x18] ; USART0_FDV
bx lr
; -------------------------
; uart_tx_byte(r0=byte)
; uses r0, r1, r2
uart_tx_byte:
mov r2, #0xf1000000 ; USART0_CLC
ldr r1, [r2, #0x20] ; USART0_TXB
bic r1, r1, #0xff
orr r1, r0, r1
str r1, [r2, #0x20] ; USART0_TXB
tx_w:
ldr r1, [r2, #0x68] ; USART0_FCSTAT
ands r1, r1, #0x02
beq tx_w
ldr r1, [r2, #0x70] ; USART0_ICR
orr r1, r1, #2
str r1, [r2, #0x70]
b serve_watchdog
; -------------------------
; byte uart_rx_byte()
; uses r0, r1, r2
uart_rx_byte:
rx_loop:
mov r1, #0xf1000000
ldr r0, [r1, #0x68] ; USART0_FCSTAT
ands r0, r0, #0x04
beq rx_loop
rx_c:
ldr r0, [r1, #0x70] ; USART0_ICR
orr r0, r0, #4
str r0, [r1, #0x70]
ldr r0, [r1, #0x24] ; USART0_RXB
and r0, r0, #0xff
bx lr
; ------------------------
; word uart_rx_word()
; uses r0, r1, r2, r3, r4, r5
uart_rx_word:
mov r5, lr
bl uart_rx_byte
mov r4, r0, LSL#24
bl uart_rx_byte
orr r4, r4, r0, LSL#16
bl uart_rx_byte
orr r4, r4, r0, LSL#8
bl uart_rx_byte
orr r0, r4, r0
bx r5
; ----------------------------
usart_speeds:
DW 0x001901d8 ; 57600 / 0x1d8 = 122.033898 * 0x1a = 3172.881348
DW 0x000c01d8 ; 115200 / 0x1d8 = 244.067797 * 13 = 3172.881361
DW 0x000501b4 ; 230400 / 0x1b4 = 528.440367 * 0x6 = 3170.642202
DW 0x00000092 ; 460800 / 0x92 = 3156.164384
DW 0x000000c3 ; 614400 / 0xc3 = 3150.769231
DW 0x00000127 ; 921600 / 0x127 = 3124.067797
DW 0x0000018a ; 1228800 / 0x18a = 3118.781726
DW 0x00000000 ; 1600000 / 0x200 = 3125
DW 0x000001d0 ; 1500000 / 0x1d0 = 3232.758621
; -------------------------
WATCH_DOG DW 0xF4400000
PCL_62 DW 0xF4300118
STM_4 DW 0xF4B00020