changeset 8:a06573cacb6e

boot ROM re: trying to understand the code that runs after '<' received
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Wed, 17 Apr 2013 06:25:19 +0000
parents a445735685ba
children 7a84f9e42a84
files bootrom.disasm bootrom.notes
diffstat 2 files changed, 126 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/bootrom.disasm	Tue Apr 16 20:56:31 2013 +0000
+++ b/bootrom.disasm	Wed Apr 17 06:25:19 2013 +0000
@@ -8,6 +8,20 @@
       18:	ea200004 	b	0x800030
       1c:	ea200004 	b	0x800034
 
+; The following routine (starting at 0x20) is used to transfer control
+; to nCS0 application images that are designed to work with no internal
+; boot ROM "in the way", i.e., images identified by a 1 in the 0x2000 word.
+; The present routine is copied to the internal RAM and executed there.
+;
+; The routine itself takes one argument in R0 and uses it to set the
+; nIBOOT override bits in the FFFF:FB10 register.  If R0==1, bits <9:8>
+; of this register are set to 11, putting nCS0 at address 0.  If R0==0,
+; the bits are set to 01, putting the internal ROM at 0.  Otherwise,
+; the bits are set to 00, restoring the nIBOOT pin configuration.
+; (In actual operation the argument passed to this function is the word
+; from 0x2000, so it's equal to 1.)  Then the routine causes the
+; watchdog timer to go off, resetting the ARM.
+
       20:	e24dd004 	sub	sp, sp, #4	; 0x4
       24:	e59f20b8 	ldr	r2, =0xFFFFFB10	; via 0xe4
       28:	e1d2c0b0 	ldrh	r12, [r2]
@@ -58,9 +72,10 @@
       dc:	e28dd004 	add	sp, sp, #4	; 0x4
       e0:	e12fff1e 	bx	lr
 
-; literal pool
+; literal pool for the above routine
       e4:	fffffb10
       e8:	000080f5
+; end of the code copied to the internal RAM for booting type 1 images
 
       ec:	e92d4010 	stmdb	sp!, {r4, lr}
       f0:	e59fcd0c 	ldr	r12, [pc, #3340]	; 0xe04
@@ -72,7 +87,7 @@
      108:	e5d0c000 	ldrb	r12, [r0]
      10c:	e31c0040 	tst	r12, #64	; 0x40
      110:	0afffffc 	beq	0x108
-     114:	eb000513 	bl	0x1568
+     114:	eb000513 	bl	0x1568		; IND_CALL
      118:	eafffffe 	b	0x118
 
      11c:	e3a0c004 	mov	r12, #4	; 0x4
@@ -1002,16 +1017,23 @@
      eec:	e10600bc 	strh	r0, [r6, -r12]
      ef0:	e8bd8070 	ldmia	sp!, {r4, r5, r6, pc}
 
+; The routine at 0xef4 gets called from main() after a '<' character
+; has been received and autoboot thereby interrupted in the
+; autoboot-enabled flash state.
+
      ef4:	e92d4070 	stmdb	sp!, {r4, r5, r6, lr}
-     ef8:	e59fc3e4 	ldr	r12, [pc, #996]	; 0x12e4
+     ef8:	e59fc3e4 	ldr	r12, =0xFFFFF900	; via 0x12e4
      efc:	e1dc40b0 	ldrh	r4, [r12]
-     f00:	e59f33d0 	ldr	r3, [pc, #976]	; 0x12d8
+; original value of FFFF:F900 saved in R4
+; now set it to FF22, just like the 0xe2c init routine did
+     f00:	e59f33d0 	ldr	r3, =0xFFFFFD00	; via 0x12d8
      f04:	e3a05b01 	mov	r5, #1024	; 0x400
      f08:	e3a0c801 	mov	r12, #65536	; 0x10000
      f0c:	e24cc0de 	sub	r12, r12, #222	; 0xde
      f10:	e103c0b5 	strh	r12, [r3, -r5]
-     f14:	e59f63c0 	ldr	r6, [pc, #960]	; 0x12dc
-     f18:	e59fc3c0 	ldr	r12, [pc, #960]	; 0x12e0
+; write 0x2002 to FFFF:9800, again just like 0xe2c did
+     f14:	e59f63c0 	ldr	r6, =0xFFFF9800	; via 0x12dc
+     f18:	e59fc3c0 	ldr	r12, =0x2002	; via 0x12e0
      f1c:	e1c6c0b0 	strh	r12, [r6]
      f20:	e1b05f8c 	movs	r5, r12, lsl #31
      f24:	1afffffd 	bne	0xf20
@@ -1051,9 +1073,34 @@
      fac:	e10340bc 	strh	r4, [r3, -r12]
      fb0:	e8bd8070 	ldmia	sp!, {r4, r5, r6, pc}
 
+; Routine 0xfb4 gets called from main() where the boot code is giving
+; the UARTs a chance to interrupt the autoboot process before transferring
+; control to the nCS0 image.
+;
+; Arguments: both R0 and R1 point to byte variables acting as additional
+; function outputs.
+;
+; If a '<' character is received on either UART, the function returns
+; without further fuss.  If nothing was received on either UART, it
+; also returns without further fuss.  However, if the "wrong" byte value
+; was received on either UART, the function flips the VCLKOUT_DIV2 bit
+; in the FFFF:FD02 register - it is the boot code's way of figuring out
+; whether the input clock is 13 or 26 MHz.
+;
+; Return values:
+;   In R0:  1 if '<' received, 0 otherwise
+;   In *R0: UART ID if '<' received, FF otherwise
+;   In *R1: final state of the 800534 byte variable
+;
+; The latter variable records the state of the divide-by-2.  On the first
+; try, the divide-by-2 is enabled, and the variable contains 0.  When this
+; function disables the /2, the variable is set to 1.  It keeps toggling
+; back and forth as wrong bytes come in.
+
      fb4:	e3a0c0ff 	mov	r12, #255	; 0xff
      fb8:	e5c0c000 	strb	r12, [r0]
-     fbc:	e59fc324 	ldr	r12, [pc, #804]	; 0x12e8
+; check the MODEM UART first
+     fbc:	e59fc324 	ldr	r12, =0xFFFF5000	; via 0x12e8
      fc0:	e5dc2805 	ldrb	r2, [r12, #2053]
      fc4:	e1b02f82 	movs	r2, r2, lsl #31
      fc8:	1a000001 	bne	0xfd4
@@ -1063,6 +1110,9 @@
      fd8:	e352003c 	cmp	r2, #60	; 0x3c
      fdc:	0a000024 	beq	0x1074
      fe0:	e3a02001 	mov	r2, #1	; 0x1
+; Control gets here if no '<' was received on the MODEM UART.
+; R2 contains 1 if some other byte value was received, or 0 if nothing.
+; Now check the IrDA UART.
      fe4:	e5dc3005 	ldrb	r3, [r12, #5]
      fe8:	e1b03f83 	movs	r3, r3, lsl #31
      fec:	1a000002 	bne	0xffc
@@ -1072,13 +1122,14 @@
      ffc:	e5dcc000 	ldrb	r12, [r12]
     1000:	e35c003c 	cmp	r12, #60	; 0x3c
     1004:	0a000017 	beq	0x1068
-    1008:	e59fc2dc 	ldr	r12, [pc, #732]	; 0x12ec
+; control gets here if the "wrong" byte value was received on either UART
+    1008:	e59fc2dc 	ldr	r12, =0x800534	; via 0x12ec
     100c:	e5dc0000 	ldrb	r0, [r12]
     1010:	e3500000 	cmp	r0, #0	; 0x0
     1014:	1a000008 	bne	0x103c
     1018:	e3a00001 	mov	r0, #1	; 0x1
     101c:	e5cc0000 	strb	r0, [r12]
-    1020:	e59f02c8 	ldr	r0, [pc, #712]	; 0x12f0
+    1020:	e59f02c8 	ldr	r0, =0xFFFFFD02	; via 0x12f0
     1024:	e1d0c0b0 	ldrh	r12, [r0]
     1028:	e20c20bf 	and	r2, r12, #191	; 0xbf
     102c:	e20cccff 	and	r12, r12, #65280	; 0xff00
@@ -1087,22 +1138,23 @@
     1038:	ea000005 	b	0x1054
     103c:	e3a00000 	mov	r0, #0	; 0x0
     1040:	e5cc0000 	strb	r0, [r12]
-    1044:	e59fc2a4 	ldr	r12, [pc, #676]	; 0x12f0
+    1044:	e59fc2a4 	ldr	r12, =0xFFFFFD02	; via 0x12f0
     1048:	e1dc00b0 	ldrh	r0, [r12]
     104c:	e3800040 	orr	r0, r0, #64	; 0x40
     1050:	e1cc00b0 	strh	r0, [r12]
-    1054:	e59fc290 	ldr	r12, [pc, #656]	; 0x12ec
+    1054:	e59fc290 	ldr	r12, =0x800534	; via 0x12ec
     1058:	e5dcc000 	ldrb	r12, [r12]
     105c:	e5c1c000 	strb	r12, [r1]
     1060:	e3a00000 	mov	r0, #0	; 0x0
     1064:	e12fff1e 	bx	lr
-
+; control gets here if a '<' character was received on the IrDA UART
     1068:	e3a0c001 	mov	r12, #1	; 0x1
     106c:	e5c0c000 	strb	r12, [r0]
     1070:	ea000001 	b	0x107c
+; control gets here if a '<' character was received on the MODEM UART
     1074:	e3a0c000 	mov	r12, #0	; 0x0
     1078:	e5c0c000 	strb	r12, [r0]
-    107c:	e59fc268 	ldr	r12, [pc, #616]	; 0x12ec
+    107c:	e59fc268 	ldr	r12, =0x800534	; via 0x12ec
     1080:	e5dcc000 	ldrb	r12, [r12]
     1084:	e5c1c000 	strb	r12, [r1]
     1088:	e3a00001 	mov	r0, #1	; 0x1
@@ -1248,7 +1300,9 @@
     1240:	e59f10b0 	ldr	r1, =0x800524	; via 0x12f8
     1244:	e2415004 	sub	r5, r1, #4	; 0x4
     1248:	e59f40b0 	ldr	r4, =0x373C	; via 0x1300
+; the retry count loaded into R4 is 14140 in decimal
     124c:	e1a00005 	mov	r0, r5
+; call made with R0=0x800520, R1=0x800524
     1250:	ebffff57 	bl	0xfb4
     1254:	e3500000 	cmp	r0, #0	; 0x0
     1258:	1a000001 	bne	0x1264
@@ -1300,9 +1354,16 @@
     12fc:	00800104
     1300:	0000373c
 
+; Routine 0x1304: emit a character string through a UART
+;
+; Arguments:
+:   R0: pointer to the string
+;   R1: number of characters (bytes) to transmit
+;   R2: UART ID (0=MODEM, 1=IrDA)
+
     1304:	e3510000 	cmp	r1, #0	; 0x0
     1308:	012fff1e 	bxeq	lr
-    130c:	e59fc178 	ldr	r12, [pc, #376]	; 0x148c
+    130c:	e59fc178 	ldr	r12, =0x1FCC	; via 0x148c
     1310:	e79cc102 	ldr	r12, [r12, r2, lsl #2]
     1314:	e28c3005 	add	r3, r12, #5	; 0x5
     1318:	e5d32000 	ldrb	r2, [r3]
@@ -1375,7 +1436,12 @@
     13d0:	1affffed 	bne	0x138c
     13d4:	e8bd8ff0 	ldmia	sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
 
-    13d8:	e59fc0ac 	ldr	r12, [pc, #172]	; 0x148c
+; The following routine switches a UART to a different baud rate.
+; Arguments:
+;   R0: baud rate index from the table at 0x1FD4
+;   R1: UART ID (0=MODEM, 1=IrDA)
+
+    13d8:	e59fc0ac 	ldr	r12, =0x1FCC	; via 0x148c
     13dc:	e79c2101 	ldr	r2, [r12, r1, lsl #2]
     13e0:	e282c005 	add	r12, r2, #5	; 0x5
     13e4:	e5dc1000 	ldrb	r1, [r12]
@@ -1385,7 +1451,7 @@
     13f4:	e5dc1000 	ldrb	r1, [r12]
     13f8:	e3811080 	orr	r1, r1, #128	; 0x80
     13fc:	e5cc1000 	strb	r1, [r12]
-    1400:	e59f108c 	ldr	r1, [pc, #140]	; 0x1494
+    1400:	e59f108c 	ldr	r1, =0x1FD4	; via 0x1494
     1404:	e7d13080 	ldrb	r3, [r1, r0, lsl #1]
     1408:	e5c23001 	strb	r3, [r2, #1]
     140c:	e0810080 	add	r0, r1, r0, lsl #1
@@ -1396,16 +1462,25 @@
     1420:	e5cc0000 	strb	r0, [r12]
     1424:	e12fff1e 	bx	lr
 
+; 0x1428 - UART read Rx character routine
+;
+; Arguments:
+;   R0: UART ID (0=MODEM, 1=IrDA)
+;   R1: poll repeat count, 0 means wait forever
+;   R2: pointer to buffer where the received booty is stored
+;
+; Return value: 1 if a character was received, 0 otherwise
+
     1428:	e3510000 	cmp	r1, #0	; 0x0
     142c:	1a000006 	bne	0x144c
-    1430:	e59fc054 	ldr	r12, [pc, #84]	; 0x148c
+    1430:	e59fc054 	ldr	r12, =0x1FCC	; via 0x148c
     1434:	e79cc100 	ldr	r12, [r12, r0, lsl #2]
     1438:	e28c1005 	add	r1, r12, #5	; 0x5
     143c:	e5d10000 	ldrb	r0, [r1]
     1440:	e1b00f80 	movs	r0, r0, lsl #31
     1444:	0afffffc 	beq	0x143c
     1448:	ea000009 	b	0x1474
-    144c:	e59fc038 	ldr	r12, [pc, #56]	; 0x148c
+    144c:	e59fc038 	ldr	r12, =0x1FCC	; via 0x148c
     1450:	e79cc100 	ldr	r12, [r12, r0, lsl #2]
     1454:	e28c3005 	add	r3, r12, #5	; 0x5
     1458:	e5d30000 	ldrb	r0, [r3]
@@ -1521,6 +1596,11 @@
 
     1588:	eafffffe 	b	0x1588
 
+; This routine effects the transfer of control to the flash (nCS0)
+; application image of the type indicated by the argument in R0.
+; The latter argument is the word read from 0x2000.
+; R1 contains the word read from 0x2004.
+
     158c:	e92d4010 	stmdb	sp!, {r4, lr}
     1590:	e1a04000 	mov	r4, r0
     1594:	e1b0c0a4 	movs	r12, r4, lsr #1
@@ -1539,7 +1619,7 @@
     15c8:	e38ccc01 	orr	r12, r12, #256	; 0x100
     15cc:	e1c0c0b0 	strh	r12, [r0]
     15d0:	e1a04001 	mov	r4, r1
-    15d4:	ebffffe3 	bl	0x1568
+    15d4:	ebffffe3 	bl	0x1568		; IND_CALL
     15d8:	e8bd8010 	ldmia	sp!, {r4, pc}
     15dc:	e3540001 	cmp	r4, #1	; 0x1
     15e0:	18bd8010 	ldmneia	sp!, {r4, pc}
@@ -1555,10 +1635,20 @@
     1600:	fffffb10
     1604:	00800038
 
+; This routine computes a simple word-wise (16 bits at a time) sum of
+; the present internal boot ROM code (ignoring carry-outs), and returns
+; it in R0.  The upper 16 bits of the R0 return value will always be 0.
+;
+; If the argument in R0 equals 1, a call to the 0xe2c memmap/clock init
+; function is made first, with the same arguments as at the beginning
+; of main().
+
     1608:	e92d4000 	stmdb	sp!, {lr}
     160c:	e24dd008 	sub	sp, sp, #8	; 0x8
     1610:	e3500001 	cmp	r0, #1	; 0x1
     1614:	1a000006 	bne	0x1634
+; 0xe2c routine is called with the same arguments as at the beginning
+; of main()
     1618:	e3a0c002 	mov	r12, #2	; 0x2
     161c:	e5cdc000 	strb	r12, [sp]
     1620:	e3a00004 	mov	r0, #4	; 0x4
@@ -1789,10 +1879,13 @@
 ; base addresses of the two UARTs
     1fcc:	ffff5800
     1fd0:	ffff5000
-; ???
-    1fd4:	0e000700 	cdpeq	7, 0, cr0, cr0, cr0, {0}
-    1fd8:	1c001500 	cfstr32ne	mvfx1, [r0]
-    1fdc:	00002a00 	andeq	r2, r0, r0, lsl #20
+; UART baud rates
+    1fd4:	0700	; /7	(115200?)
+    1fd6:	0e00	; /14	(57600?)
+    1fd8:	1500	; /21	(38400?)
+    1fda:	1c00	; /28	(28800?)
+    1fdc:	2a00	; /42	(19200?)
+    1fde:	0000
 
 ; These ldr-jump instructions get copied to the 7 internal RAM words
 ; starting at 0x80001C.  They have the effect of defining the preceding
--- a/bootrom.notes	Tue Apr 16 20:56:31 2013 +0000
+++ b/bootrom.notes	Wed Apr 17 06:25:19 2013 +0000
@@ -37,11 +37,19 @@
 80001C 7 words:
 	hard vectors: the physical vector locations in the ROM
 	contain branch instructions to these 7 RAM addresses
-
+800038:	The helper routine for transferring control to type 1 flash images
+	is copied to and run here.
+800100:	the last word of the above routine
 800104: word initialized to 0x0001D4C0
 800108: byte initialized to 0x01
 
-800534: byte initialized to 0x00
+800520: byte variable filled every time the 0xfb4 routine is called
+	holds the ID of the UART on which '<' came in, or FF if none
+800524: byte variable filled every time the 0xfb4 routine is called
+	filled with a copy of 800534
+
+800534: byte initialized to 0x00, then may be set to 1 by the 0xfb4
+	routine if it selects /1 clock mode.
 
 8005C0: appears to be the intended low address (bottom) of the stack
 80074C: top of the stack (initial value loaded into SP)