i2cutils 48.7 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.PMF.i2cutils

; Authors JBiggs (m2), PFellows, TDobson, AGodwin

Neil Turton's avatar
Neil Turton committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
; ***********************************
; ***    C h a n g e   L i s t    ***
; ***********************************

; Date       Name  Description
; ----       ----  -----------
; 28-Mar-95  JRH   Added support for E2ROMs and/or CMOS, conditioned on
;                  E2ROMSupport which is defined elsewhere
;                  Uses RTCFitted and NVRamSize in KernelWS
; 03-Jul-96  JRH   Took out code conditioned on :LNOT: NewClockChip
;                  Fixed support for E2ROM. E2 works in the same gross way as
;                  CMOS. Any E2 fitted > 256 bytes will not be accessed by these
;                  routines.
; amg 7/12/96 Renaissance. Leave this file as is, allowing the E2ROMSupport
;             switch to disable non-STB bits
Kevin Bracey's avatar
Kevin Bracey committed
34 35 36
; 12-Jun-97  TMD   (Really) fix OTP access problem.
; 17-Sep-98  KJB   Add support for 16K 24C128 EEPROM.
; 21-Sep-98  KJB   Add OS_NVMemory SWI.
37
; 30-Jul-99  KJB   Add support for 8K 24C64 EEPROM.
38
; 23-Sep-99  KJB   Remove support for 24C64, add support for 4K and 8K protectable ATMEL parts.
Neil Turton's avatar
Neil Turton committed
39 40 41

PhysChecksum	*	(((CheckSumCMOS + &30) :MOD: &F0) + &10)

Kevin Bracey's avatar
Kevin Bracey committed
42 43
PollMax		*	150	; Number of times to poll for an Ack (increase if you clock faster - need to
                                ; allow 5ms for write cycle).
Neil Turton's avatar
Neil Turton committed
44 45

; Device addresses
Kevin Bracey's avatar
Kevin Bracey committed
46
RTCAddress		*	&a0     ; traditional RTC / 240 byte CMOS
Neil Turton's avatar
Neil Turton committed
47
  [	E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
48 49 50
E2ROMAddress		*	&a8     ; 24C08 device - 512 byte or 1K
E2ROMAddress2K		*	&e0     ; 24C174 device - 2K
E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
51 52
E2ROMAddress4K          *       &a4     ; 24C32 device - 4K (top 1K protectable)
E2ROMAddress8K          *       &a2     ; 24C64 device - 8K (top 2K protectable)
Kevin Bracey's avatar
Kevin Bracey committed
53
E2ROMAddress16K         *       &a8     ; 24C128 device - 16K
Robert Catherall's avatar
Robert Catherall committed
54 55 56 57 58 59 60 61 62 63 64 65 66
E2ROMAddress32K         *       &a6     ; 24CS256 device - 32K (top 2K possibly OTP)
  ]

; Choose a lower limit on the number of ticks per clock phase based on the
; MaxI2Cspeed variable defined in Hdr:Machine.<Machine>
  [ MaxI2Cspeed >= 1000
I2Cticks        *       1
  |
  [ MaxI2Cspeed >= 400
I2Cticks        *       3
  |
I2Cticks        *       10
  ]
Neil Turton's avatar
Neil Turton committed
67 68
  ]

Neil Turton's avatar
Neil Turton committed
69 70
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
71
;	HexToBCD - Convert byte in hex to BCD
Neil Turton's avatar
Neil Turton committed
72
;
Neil Turton's avatar
Neil Turton committed
73
; in:	R0 = byte in hex
Neil Turton's avatar
Neil Turton committed
74
;
Neil Turton's avatar
Neil Turton committed
75 76
; out:	R0 = byte in BCD (ie R0 := (R0 DIV 10)*16 + R0 MOD 10)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
77 78 79
;

HexToBCD ROUT
Neil Turton's avatar
Neil Turton committed
80 81 82 83 84
	Push	"R1,R2, R14"
	MOV	R1, #10
	DivRem	R2, R0, R1, R14			; R2=R0 DIV 10; R0=R0 MOD 10
	ADD	R0, R0, R2, LSL #4
	Pull	"R1,R2, PC"
Neil Turton's avatar
Neil Turton committed
85 86 87

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
88
;	BCDToHex - Convert byte in BCD to hex
Neil Turton's avatar
Neil Turton committed
89
;
Neil Turton's avatar
Neil Turton committed
90
; in:	R0 = byte in BCD (ie x*16 + y)
Neil Turton's avatar
Neil Turton committed
91
;
Neil Turton's avatar
Neil Turton committed
92 93
; out:	R0 = byte in hex (ie x*10 + y)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
94 95 96
;

BCDToHex ROUT
Neil Turton's avatar
Neil Turton committed
97 98 99 100 101
	Push	"R14"
	MOV	R14, R0, LSR #4			; R14 := x
	ADD	R14, R14, R14, LSL #1		; R14 := x*3
	SUB	R0, R0, R14, LSL #1		; R0 := R0 - x*6 = x*10
	Pull	"PC"
Neil Turton's avatar
Neil Turton committed
102 103 104

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
105
;	SetC1C0 - Set clock and data lines to values in R1 and R0 respectively
Neil Turton's avatar
Neil Turton committed
106
;
Neil Turton's avatar
Neil Turton committed
107
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
108 109 110
;

SetC1C0 ROUT
Kevin Bracey's avatar
Kevin Bracey committed
111 112
 [ No26bitCode
	Push	"R0-R3,R14"
113
        MRS     R3, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
114
 |
Neil Turton's avatar
Neil Turton committed
115
	Push	"R0-R2,R14"
Kevin Bracey's avatar
Kevin Bracey committed
116
 ]
Neil Turton's avatar
Neil Turton committed
117
	ADD	R0, R0, R1, LSL #1	; R0 := C0 + C1*2
Neil Turton's avatar
Neil Turton committed
118

Neil Turton's avatar
Neil Turton committed
119 120 121 122 123 124 125 126 127 128 129
	[ AssemblingArthur :LOR: Module
	MOV	R2, #0				; prepare to index soft copy
	LDRB	R1, [R2, #IOCControlSoftCopy]	; read soft copy
	BIC	R1, R1, #&03			; clear clock and data
	ORR	R0, R1, R0			; put in new clock and data
	ORR	R0, R0, #&C0			; make sure two test bits are
						; always set to 1 !
	STRB	R0, [R2, #IOCControlSoftCopy]	; store back to soft copy
	|
	ORR	R0, R0, #&FC			; set other bits to 1
	]
Neil Turton's avatar
Neil Turton committed
130

Neil Turton's avatar
Neil Turton committed
131 132
	MOV	R2, #IOC
	STRB	R0, [R2, #IOCControl]
Neil Turton's avatar
Neil Turton committed
133

134
      [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
135 136 137 138 139 140 141 142
        [ :LNOT: :DEF: TestHarness
        MOV	R0, #0
        LDRB	R0, [R0, #NVRamSpeed]
        |
        LDRB	R0, NVSpeed
        ]
        TEQ     R0, #0
        MOVEQ   R0, #10                         ; default value if speed not checked yet
143 144 145
      |
        MOV     R0, #10                         ; default to slowest value if we have E2ROMSupport is false
      ]
Neil Turton's avatar
Neil Turton committed
146
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
147

Kevin Bracey's avatar
Kevin Bracey committed
148
 [ No26bitCode
149
        MSR     CPSR_f, R3
Kevin Bracey's avatar
Kevin Bracey committed
150 151
	Pull	"R0-R3,PC"
 |
Neil Turton's avatar
Neil Turton committed
152
	Pull	"R0-R2,PC",,^
Kevin Bracey's avatar
Kevin Bracey committed
153
 ]
Neil Turton's avatar
Neil Turton committed
154 155 156

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
157
;	DoMicroDelay - Delay for >= R0/2 microseconds
Neil Turton's avatar
Neil Turton committed
158
;
Neil Turton's avatar
Neil Turton committed
159 160 161
; in:	R0 = time delay in 1/2 microsecond units
;	R2 -> IOC
;	On ARM600, we may or may not be in a 32-bit mode
Neil Turton's avatar
Neil Turton committed
162
;
Neil Turton's avatar
Neil Turton committed
163
; out:	R0,R1 corrupted
Neil Turton's avatar
Neil Turton committed
164 165 166
;

DoMicroDelay ROUT
Neil Turton's avatar
Neil Turton committed
167
	Push	R14
Neil Turton's avatar
Neil Turton committed
168

Neil Turton's avatar
Neil Turton committed
169 170
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R1, [R2, #Timer0CL]	; R1 := low output latch
Neil Turton's avatar
Neil Turton committed
171
10
Neil Turton's avatar
Neil Turton committed
172 173 174 175 176 177 178
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R14, [R2, #Timer0CL]	; R14 := low output latch
	TEQ	R14, R1			; unchanged ?
	BEQ	%BT10			; then loop
	MOV	R1, R14			; copy anyway
	SUBS	R0, R0, #1		; decrement count
	BNE	%BT10			; loop if not finished
Neil Turton's avatar
Neil Turton committed
179

Neil Turton's avatar
Neil Turton committed
180
	Pull	PC
Neil Turton's avatar
Neil Turton committed
181

Neil Turton's avatar
Neil Turton committed
182
	LTORG
Neil Turton's avatar
Neil Turton committed
183 184 185

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
186
;	ClockData - Clock a bit of data down the IIC bus
Neil Turton's avatar
Neil Turton committed
187
;
Neil Turton's avatar
Neil Turton committed
188
; in:	R0 = data bit
Neil Turton's avatar
Neil Turton committed
189
;
Neil Turton's avatar
Neil Turton committed
190
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
191 192 193
;

ClockData ROUT
Kevin Bracey's avatar
Kevin Bracey committed
194 195
 [ No26bitCode
	Push	"R1,R2,R14"
196
        MRS     R2,CPSR
Kevin Bracey's avatar
Kevin Bracey committed
197
 |
Neil Turton's avatar
Neil Turton committed
198
	Push	"R1, R14"
Kevin Bracey's avatar
Kevin Bracey committed
199
 ]
Neil Turton's avatar
Neil Turton committed
200

Neil Turton's avatar
Neil Turton committed
201 202
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
203

Kevin Bracey's avatar
Kevin Bracey committed
204 205
 [ No26bitCode
        ORR     R1,R2,#I32_bit
206
        MSR     CPSR_c,R1
Kevin Bracey's avatar
Kevin Bracey committed
207
 |
Neil Turton's avatar
Neil Turton committed
208 209 210
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

Neil Turton's avatar
Neil Turton committed
211 212 213
	MOV	R1,PC
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
214
 ]
Neil Turton's avatar
Neil Turton committed
215 216
	MOV	R1, #1			; Clock hi
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
217 218 219

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
220 221
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
222

Kevin Bracey's avatar
Kevin Bracey committed
223
 [ No26bitCode
224
        MSR     CPSR_cf,R2              ; Restore interrupts
Kevin Bracey's avatar
Kevin Bracey committed
225 226
        Pull    "R1,R2,PC"
 |
Neil Turton's avatar
Neil Turton committed
227
	Pull	"R1, PC",,^
Kevin Bracey's avatar
Kevin Bracey committed
228
 ]
Neil Turton's avatar
Neil Turton committed
229

Neil Turton's avatar
Neil Turton committed
230 231 232
ClockData0 ROUT				; Clock a zero bit
	Push	"R0, R14"
	MOV	R0, #0
Kevin Bracey's avatar
Kevin Bracey committed
233 234
	BL	ClockData               ; preserves PSR
	Pull	"R0, PC"
Neil Turton's avatar
Neil Turton committed
235 236 237

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
238
;	Start - Send the Start signal
Neil Turton's avatar
Neil Turton committed
239
;
Neil Turton's avatar
Neil Turton committed
240
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
241 242
;

Neil Turton's avatar
Neil Turton committed
243
Start	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
244 245
 [ No26bitCode
	Push	"R0-R3,R14"
246
        MRS     R3, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
247
 |
Neil Turton's avatar
Neil Turton committed
248
	Push	"R0-R2,R14"
Kevin Bracey's avatar
Kevin Bracey committed
249
 ]
Neil Turton's avatar
Neil Turton committed
250

Neil Turton's avatar
Neil Turton committed
251 252 253
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
254

Kevin Bracey's avatar
Kevin Bracey committed
255
; Delay here must be >= 4.7 microsecs (1.3 for fast device)
Neil Turton's avatar
Neil Turton committed
256

Neil Turton's avatar
Neil Turton committed
257 258 259
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
260

Robert Catherall's avatar
Robert Catherall committed
261
 [ I2Cticks >= 10
Neil Turton's avatar
Neil Turton committed
262 263
; Hold start condition for BMU

Neil Turton's avatar
Neil Turton committed
264
	MOV	R2, #IOC
Kevin Bracey's avatar
Kevin Bracey committed
265
        MOV     R0, #10
Neil Turton's avatar
Neil Turton committed
266
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
267 268
 ]

Kevin Bracey's avatar
Kevin Bracey committed
269
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
270

Neil Turton's avatar
Neil Turton committed
271 272 273
	MOV	R0, #0			; clock LO, data LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
274

Kevin Bracey's avatar
Kevin Bracey committed
275
 [ No26bitCode
276
        MSR     CPSR_f, R3
Kevin Bracey's avatar
Kevin Bracey committed
277 278 279 280
	Pull	"R0-R3,PC"
 |
	Pull	"R0-R2,PC"
 ]
Neil Turton's avatar
Neil Turton committed
281 282 283

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
284
;	Acknowledge - Check acknowledge after transmitting a byte
Neil Turton's avatar
Neil Turton committed
285
;
Neil Turton's avatar
Neil Turton committed
286 287 288
; out:	All registers preserved
;	V=0 => acknowledge received
;	V=1 => no acknowledge received
Neil Turton's avatar
Neil Turton committed
289 290 291
;

Acknowledge ROUT
Neil Turton's avatar
Neil Turton committed
292
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
293

Neil Turton's avatar
Neil Turton committed
294 295 296
	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
297 298 299 300 301

 [ {TRUE}
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

302
        MRS     R1,CPSR
Kevin Bracey's avatar
Kevin Bracey committed
303 304
        Push    "R1"
        ORR     R1,R1,#I32_bit
305
        MSR     CPSR_c,R1
Neil Turton's avatar
Neil Turton committed
306
 ]
Neil Turton's avatar
Neil Turton committed
307 308 309
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
310

Kevin Bracey's avatar
Kevin Bracey committed
311
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
312

Neil Turton's avatar
Neil Turton committed
313 314
	MOV	R2, #IOC
	LDRB	R2, [R2, #IOCControl]	; get the data from IOC
Neil Turton's avatar
Neil Turton committed
315

Neil Turton's avatar
Neil Turton committed
316 317 318
	MOV	R0, #0
	MOV	R1, #0			; clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
319 320

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
321
	Pull	"R1"
322
	MSR     CPSR_c,R1
Neil Turton's avatar
Neil Turton committed
323 324
 ]

Neil Turton's avatar
Neil Turton committed
325
	TST	R2, #1			; should be LO for correct acknowledge
326
        MRS     R2, CPSR
Neil Turton's avatar
Neil Turton committed
327 328
	BICEQ	R2, R2, #V_bit		; clear V if correct acknowledge
	ORRNE	R2, R2, #V_bit		; set V if no acknowledge
329
        MSR     CPSR_f, R2
Neil Turton's avatar
Neil Turton committed
330

Neil Turton's avatar
Neil Turton committed
331
	Pull	"R0-R2,PC"
Neil Turton's avatar
Neil Turton committed
332 333 334

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
335
;	Stop - Send the Stop signal
Neil Turton's avatar
Neil Turton committed
336
;
Neil Turton's avatar
Neil Turton committed
337
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
338 339
;

Neil Turton's avatar
Neil Turton committed
340
Stop	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
341 342
 [ No26bitCode
	Push	"R0-R2,R14"
343
        MRS     R2, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
344
 |
Neil Turton's avatar
Neil Turton committed
345
	Push	"R0,R1,R14"
Kevin Bracey's avatar
Kevin Bracey committed
346
 ]
Neil Turton's avatar
Neil Turton committed
347

Neil Turton's avatar
Neil Turton committed
348 349 350
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
351

Kevin Bracey's avatar
Kevin Bracey committed
352
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
353

Neil Turton's avatar
Neil Turton committed
354 355 356
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
357

Kevin Bracey's avatar
Kevin Bracey committed
358
 [ No26bitCode
359
        MSR     CPSR_f, R2
Kevin Bracey's avatar
Kevin Bracey committed
360 361
	Pull	"R0-R2,PC"
 |
Neil Turton's avatar
Neil Turton committed
362
	Pull	"R0,R1,PC",,^
Kevin Bracey's avatar
Kevin Bracey committed
363
 ]
Neil Turton's avatar
Neil Turton committed
364 365 366

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
367
;	TXByte - Transmit a byte
Neil Turton's avatar
Neil Turton committed
368
;
Neil Turton's avatar
Neil Turton committed
369
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
370
;
Neil Turton's avatar
Neil Turton committed
371
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
372 373
;

Neil Turton's avatar
Neil Turton committed
374
TXByte	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
375 376
 [ No26bitCode
	Push	"R0-R3,R14"
377
        MRS     R3, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
378
 |
Neil Turton's avatar
Neil Turton committed
379
	Push	"R0-R2,R14"
Kevin Bracey's avatar
Kevin Bracey committed
380
 ]
Neil Turton's avatar
Neil Turton committed
381
	MOV	R1, #&80		; 2^7 the bit mask
Kevin Bracey's avatar
Kevin Bracey committed
382
	MOV	R2, R0			; byte goes into R2
Neil Turton's avatar
Neil Turton committed
383
10
Neil Turton's avatar
Neil Turton committed
384 385 386 387 388
	ANDS	R0, R2, R1		; zero if bit is zero
	MOVNE	R0, #1
	BL	ClockData		; send the bit
	MOVS	R1, R1, LSR #1
	BNE	%BT10
Kevin Bracey's avatar
Kevin Bracey committed
389
 [ No26bitCode
390
        MSR     CPSR_f, R3
Kevin Bracey's avatar
Kevin Bracey committed
391 392
	Pull	"R0-R3,PC"
 |
Neil Turton's avatar
Neil Turton committed
393
	Pull	"R0-R2,PC",,^
Kevin Bracey's avatar
Kevin Bracey committed
394
 ]
Neil Turton's avatar
Neil Turton committed
395 396 397

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
398 399 400 401 402 403
;	StartTXPollAck - Transmit start and a byte and poll for acknowledge
;
;	This is intended for devices with a slow internal write cycle which
;	don't ack until the write cycle is finished ( eg ATMEL AT24C01A/x )
;
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
404
;
Neil Turton's avatar
Neil Turton committed
405
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
406 407
;

Neil Turton's avatar
Neil Turton committed
408
StartTXPollAck	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
409 410
 [ No26bitCode
	Push	"R1,R3,R14"
411
        MRS     R3, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
412
 |
Neil Turton's avatar
Neil Turton committed
413
	Push	"R1,R14"
Kevin Bracey's avatar
Kevin Bracey committed
414
 ]
Neil Turton's avatar
Neil Turton committed
415 416 417 418 419 420 421 422 423 424 425 426 427
	MOV	R1, #0
10
	INC	R1
	CMP	R1, #PollMax
	Pull	"R1,pc", EQ

	BL	Start
	BL	TXByte
	BL	Acknowledge
	BVS	%BT10
 [	{FALSE}
	BREG	R1, "i2c tries:"
 ]
Kevin Bracey's avatar
Kevin Bracey committed
428
 [ No26bitCode
429
        MSR     CPSR_f, R3
Kevin Bracey's avatar
Kevin Bracey committed
430 431
	Pull	"R1,R3,PC"
 |
Neil Turton's avatar
Neil Turton committed
432
	Pull	"R1,pc",,^
Kevin Bracey's avatar
Kevin Bracey committed
433
 ]
Neil Turton's avatar
Neil Turton committed
434

Neil Turton's avatar
Neil Turton committed
435 436 437 438 439 440 441 442 443
; *****************************************************************************
;
;	RXByte - Receive a byte
;
; out:	R0 = byte received
;	All other registers preserved, including PSR
;

RXByte	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
444 445
 [ No26bitCode
	Push	"R1-R5, R14"
446
        MRS     R5, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
447
 |
Neil Turton's avatar
Neil Turton committed
448
	Push	"R1-R4, R14"
Kevin Bracey's avatar
Kevin Bracey committed
449
 ]
Neil Turton's avatar
Neil Turton committed
450 451 452 453 454 455 456
	MOV	R3, #0			; byte:=0
	MOV	R2, #IOC
	MOV	R4, #7

	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
457 458 459 460 461
10
 [ {TRUE}
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

462
        MRS     R1,CPSR
Kevin Bracey's avatar
Kevin Bracey committed
463 464
        Push    "R1"
        ORR     R1,R1,#I32_bit
465
        MSR     CPSR_c,R1
Neil Turton's avatar
Neil Turton committed
466
 ]
Neil Turton's avatar
Neil Turton committed
467 468 469
	MOV	R0, #1			; pulse clock HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
470

Neil Turton's avatar
Neil Turton committed
471 472 473
	LDRB	R1, [R2, #IOCControl]	; get the data from IOC
	AND	R1, R1, #1
	ADD	R3, R1, R3, LSL #1	; byte:=byte*2+(IOC?0)AND1
Neil Turton's avatar
Neil Turton committed
474

Neil Turton's avatar
Neil Turton committed
475 476 477
	MOV	R0, #1			; return clock LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
478 479

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
480
	Pull	"R1"
481
	MSR     CPSR_c,R1
Neil Turton's avatar
Neil Turton committed
482
 ]
Neil Turton's avatar
Neil Turton committed
483 484 485 486
	SUBS	R4, R4, #1
	BCS	%BT10

	MOV	R0, R3			; return the result in R0
Kevin Bracey's avatar
Kevin Bracey committed
487
 [ No26bitCode
488
        MSR     CPSR_f, R5
Kevin Bracey's avatar
Kevin Bracey committed
489 490
	Pull	"R1-R5, PC"
 |
Neil Turton's avatar
Neil Turton committed
491
	Pull	"R1-R4, PC",,^
Kevin Bracey's avatar
Kevin Bracey committed
492
 ]
Neil Turton's avatar
Neil Turton committed
493 494 495 496 497 498 499 500

; *****************************************************************************

HTBTA	ROUT
	Push	R14
	BL	HexToBCD
	BL	TXAck
	Pull	PC
Neil Turton's avatar
Neil Turton committed
501

Neil Turton's avatar
Neil Turton committed
502 503 504 505 506 507 508 509 510 511 512 513
TXAck	ROUT
	Push	R14
	BL	TXByte
	BL	Acknowledge
	Pull	PC

CD0RBTH ROUT
	Push	R14
	BL	ClockData0
	BL	RXByte
	BL	BCDToHex
	Pull	PC
Neil Turton's avatar
Neil Turton committed
514 515 516

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
517
;	Write - Write a byte of CMOS RAM specified by logical address
Neil Turton's avatar
Neil Turton committed
518
;
Neil Turton's avatar
Neil Turton committed
519 520
; in:	R0 = address in CMOS RAM
;	R1 = data
Neil Turton's avatar
Neil Turton committed
521
;
Neil Turton's avatar
Neil Turton committed
522
; out:	All registers preserved
Neil Turton's avatar
Neil Turton committed
523 524
;

Kevin Bracey's avatar
Kevin Bracey committed
525 526 527 528 529 530 531 532 533
WriteWithError ROUT
        Push    "R0-R4, R14"
        BL      MangleCMOSAddress
        BCC     %FT05

        ADD     R13, R13, #4            ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
534 535
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
536
 ]
Kevin Bracey's avatar
Kevin Bracey committed
537
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
538 539 540

        MakeErrorBlock CoreNotWriteable

Robert Catherall's avatar
Robert Catherall committed
541 542 543 544 545 546 547 548 549 550 551
WriteWithoutProtection                  ; allowing write to "OTP" and protected section
        Push    "R0-R4, R14"
        BL      MangleCMOSAddress
        Pull    "R0-R4, PC", CS         ; if invalid, then exit
        MOV     R2, R0
        MOV     R3, R1
        CMP     R0, #&10
        MOVLO   R4, #&1000000           ; don't change checksum for OTP
        BLO     %FT10
        B       %FT08                   ; do change checksum for protected region

Kevin Bracey's avatar
Kevin Bracey committed
552
Write
Neil Turton's avatar
Neil Turton committed
553 554 555
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Kevin Bracey's avatar
Kevin Bracey committed
556 557 558 559 560
05
  [ E2ROMSupport
        CMP     r0, #&10
        Pull    "R0-R4, PC", CC         ; don't write to OTP section
  ]
Neil Turton's avatar
Neil Turton committed
561

Stewart Brodie's avatar
Stewart Brodie committed
562
  [ E2ROMSupport
563 564
        MOV     R14, #0                 ; don't write to protected section
        LDRB    R14, [R14, #NVRamWriteSize]
565
        CMP     R0, R14, LSL #8         ; (note assumption that NVRamWriteSize is
566
        Pull    "R0-R4, PC", HS         ; outside mangled region).
Stewart Brodie's avatar
Stewart Brodie committed
567
  ]
568

Neil Turton's avatar
Neil Turton committed
569 570
	MOV	R2, R0
	MOV	R3, R1
Robert Catherall's avatar
Robert Catherall committed
571
08
Neil Turton's avatar
Neil Turton committed
572 573 574 575 576 577 578
 [ ChecksumCMOS
	BL	ReadStraight		; calculate new checksum :
	MOV	R4, R0
	MOV	R0, #PhysChecksum
	BL	ReadStraight
	SUB	R0, R0, R4		; = oldsum - oldcontents
	ADD	R4, R0, R3		;          + newcontents
Neil Turton's avatar
Neil Turton committed
579

Neil Turton's avatar
Neil Turton committed
580 581 582 583
	AND	R4, R4, #&FF
	CMPS	R2, #PhysChecksum	; don't write new checksum ...
	ORREQ	R4, R4, #&1000000	; if checksum is being written
 ]
Neil Turton's avatar
Neil Turton committed
584 585
10
 [ CacheCMOSRAM
Kevin Bracey's avatar
Kevin Bracey committed
586 587 588 589 590 591
	CMP	r2, #&100		; check small cache limit
	BCS	%FT15
  [ :LNOT: :DEF: TestHarness
	LDR	R1, =CMOSRAMCache	; update cache, but always write to
  |
        ADR     R1, i2cWorkSpace
Neil Turton's avatar
Neil Turton committed
592 593
  ]
	STRB	R3, [R1, R2]		; real hardware as well
Kevin Bracey's avatar
Kevin Bracey committed
594
15
Neil Turton's avatar
Neil Turton committed
595 596 597 598 599 600 601
 ]
 [ E2ROMSupport
	MOV	R0, R2
	BL	GetI2CAddress		; convert to device address + offset
	MOV	R2, R0			; save the offset
 |
	MOV	R1, #RTCAddress
Neil Turton's avatar
Neil Turton committed
602 603
 ]

Neil Turton's avatar
Neil Turton committed
604 605
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
606

Kevin Bracey's avatar
Kevin Bracey committed
607 608 609 610 611
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
Neil Turton's avatar
Neil Turton committed
612
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
613

Neil Turton's avatar
Neil Turton committed
614 615
	MOV	R0, R3			; data
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
616

Neil Turton's avatar
Neil Turton committed
617 618 619 620 621 622 623 624 625
	BL	Stop
	[ ChecksumCMOS
	TST	R4, #&1000000		; loop again to write new checksum
	MOV	R3, R4
	MOV	R2, #PhysChecksum
	ORR	R4, R4, #&1000000	; but ensure it only happens once
	BEQ	%BT10
	]
	Pull	"R0-R4, PC"
Neil Turton's avatar
Neil Turton committed
626

Kevin Bracey's avatar
Kevin Bracey committed
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
; *****************************************************************************
;
;       WriteBlock - Write a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  All registers preserved
;


WriteBlock ROUT
        Push    "R0-R4,R14"
  [     E2ROMSupport
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
644
        LDRB    R4, [R14, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
645
        LDRB	R14, [R14, #NVRamSize]
646
        MOV     R4, R4, LSL #8
Kevin Bracey's avatar
Kevin Bracey committed
647 648
        |
        LDRB	R14, NVSize
649
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
650 651 652 653
        ]
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
654
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
655 656 657 658 659 660 661 662 663 664
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

665 666 667 668 669 670
        CMP     R0, R4                  ; ignore writes totally outside writable area
        BHS     %FT80

        SUBS    R14, R3, R4
        SUBGT   R2, R2, R14             ; truncate writes partially outside writable area

Kevin Bracey's avatar
Kevin Bracey committed
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
        TEQ     R2, #0
        BEQ     %FT80

        CMP     R0, #CheckSumCMOS       ; are we going to write the checksum byte?
        BHI     %FT03
        CMP     R3, #CheckSumCMOS
        BHS     %FT05

03
; we're not writing the checksum byte manually, so we need to update it
        MOV     R4, R1
        MOV     R1, #0
        BL      ChecksumBlock           ; find the checksum of what we're about to
        ORR     R3, R1, #&80000000      ; overwrite
        MOV     R1, R4
        B       %FT08

05      MOV     R3, #0
08      MOV     R4, #0
10      BL      WriteSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10

        TST     R3, #&80000000          ; were we going to write the checksum?
        BEQ     %FT80

        MOV     R0, #CheckSumCMOS
        BL      Read                    ; get old checksum byte
        ADD     R0, R0, R4              ; add new data checksum
        SUB     R1, R0, R3              ; subtract old checksum
        MOV     R0, #CheckSumCMOS
        BL      Write                   ; write back new checksum

80
        Pull    "R0-R4,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
713 714
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
715
 ]
Kevin Bracey's avatar
Kevin Bracey committed
716
        Pull    "R1-R4,PC"
Kevin Bracey's avatar
Kevin Bracey committed
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843

; *****************************************************************************
;
;       WriteSubBlock - Write a block of CMOS RAM specified by logical address.
;                       Assumes the address is valid, and will only read as much
;                       as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount written.
;       R4 incremented by sum of bytes written.
;
WriteSubBlock ROUT
        Push    "R3,R5-R6,R14"
        MOV     R6, R4
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

; [F0..100) -> not written
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        ADD     R1, R1, R14
        SUB     R2, R2, R14
        Pull    "R3,R5-R6,PC"

; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
 [ E2ROMSupport
; R3 = logical end of possible transaction (exclusive). Now check we don't cross page boundaries.
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamPageSize]
        |
        LDRB	R14, NVPageSize
        ]
        MOV     R5, #1
        MOV     R14, R5, LSL R14        ; R14 = (1<<pagesize)

        ADD     R5, R0, R4              ; R5 = physical start address
        ADD     R5, R5, R14
        SUB     R14, R14, #1
        BIC     R5, R5, R14             ; R5 = physical end of page with start address in
        SUB     R5, R5, R4              ; R5 = logical end of page with start address in

        CMP     R5, R3
        MOVLO   R3, R5                  ; adjust R3 to not cross page boundary
 ]

  [     CacheCMOSRAM
        CMP     R0, #&100               ; check it's a cacheable segment
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        Push    "R3, R4"
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being written
        MOV     R5, R1                  ; remember R1
12      LDRB    R14, [R1], #1           ; update cache copy
        STRB    R14, [R4], #1
        CMP     R4, R3
        BLO     %BT12
        MOV     R1, R5                  ; restore R1, and continue to update real memory
        Pull    "R3, R4"
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being written
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        LDRB    R0, [R1], #1
        ADD     R6, R6, R0              ; update checksum counter
        BL      TXAck
        SUBS    R5, R5, #1
        BNE     %BT20
Kevin Bracey's avatar
Kevin Bracey committed
844 845
                                        ; V clear
	BL	Stop                    ; preserves flags
Kevin Bracey's avatar
Kevin Bracey committed
846 847 848

        MOV     R4, R6

Kevin Bracey's avatar
Kevin Bracey committed
849
	Pull	"R0,R2,R3,R5,R6,PC"
Kevin Bracey's avatar
Kevin Bracey committed
850

Neil Turton's avatar
Neil Turton committed
851 852
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
853 854
;	Read - Read a byte of CMOS RAM specified by logical address
;	ReadStraight - Read a byte of CMOS RAM specified by physical address
Kevin Bracey's avatar
Kevin Bracey committed
855
;       ReadWithError - Read a byte of CMOS RAM specified by logical address, giving error if out of range
Neil Turton's avatar
Neil Turton committed
856
;
Neil Turton's avatar
Neil Turton committed
857
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
858
;
Kevin Bracey's avatar
Kevin Bracey committed
859
; out:	R0 = data (illegal address return 0, or error for ReadWithError)
Neil Turton's avatar
Neil Turton committed
860
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
861 862 863
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
864 865
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
866

Kevin Bracey's avatar
Kevin Bracey committed
867 868 869 870 871 872 873
ReadWithError
        Push    "R1,R2,R14"
        BL      MangleCMOSAddress
        BCC     %FT10
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
874 875
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
876
 ]
Kevin Bracey's avatar
Kevin Bracey committed
877
        Pull    "R1,R2,PC"
Kevin Bracey's avatar
Kevin Bracey committed
878 879 880

        MakeErrorBlock CoreNotReadable

Neil Turton's avatar
Neil Turton committed
881
Read
Neil Turton's avatar
Neil Turton committed
882 883 884 885
	Push	"R1,R2,R14"
	BL	MangleCMOSAddress
	MOVCS	R0, #0			; pretend illegal addresses contain 0
	Pull	"R1,R2,PC", CS
Neil Turton's avatar
Neil Turton committed
886
10
Neil Turton's avatar
Neil Turton committed
887 888 889
  [	CacheCMOSRAM
	TEQ	R0, #&40		; is it Econet station number
	BEQ	%FT15	 		; if so then don't use cache
Kevin Bracey's avatar
Kevin Bracey committed
890 891 892 893 894 895 896 897 898 899 900
        CMP     R0, #&10                ; don't cache the clock
  [     E2ROMSupport
        BHS     %FT13
        MOV     R14, #0
        LDR     R14, [R14, #RTCFitted]
        TEQ     R14, #0
        BNE     %FT15
  |
        BLO     %FT15
  ]
13	CMP	R0, #&100		; check small cache limit
Kevin Bracey's avatar
Kevin Bracey committed
901 902 903 904
  [ :LNOT: :DEF: TestHarness
	LDRCC	R2, =CMOSRAMCache	; if in range
  |
	ADRCC	R2, i2cWorkSpace
Neil Turton's avatar
Neil Turton committed
905
  ]
Kevin Bracey's avatar
Kevin Bracey committed
906 907
	LDRCCB	R0, [R2, R0]		; read from cache
	Pull	"R1,R2,PC", CC		; and exit
Neil Turton's avatar
Neil Turton committed
908 909 910
15

; else drop thru into real CMOS reading code
Neil Turton's avatar
Neil Turton committed
911
  ]
Neil Turton's avatar
Neil Turton committed
912

Neil Turton's avatar
Neil Turton committed
913 914 915 916 917
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]
Neil Turton's avatar
Neil Turton committed
918

Neil Turton's avatar
Neil Turton committed
919 920 921
	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
922

Kevin Bracey's avatar
Kevin Bracey committed
923 924 925 926 927
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
Neil Turton's avatar
Neil Turton committed
928
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
929

Neil Turton's avatar
Neil Turton committed
930
	BL	Start
Neil Turton's avatar
Neil Turton committed
931

Neil Turton's avatar
Neil Turton committed
932 933
	ADD	R0, R1, #1		; device address for read
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
934

Neil Turton's avatar
Neil Turton committed
935 936
	BL	RXByte			; returned in R0
	MOV	R2, R0			; copy to R2 for now
Neil Turton's avatar
Neil Turton committed
937

Neil Turton's avatar
Neil Turton committed
938 939
	MOV	R0, #1
	BL	ClockData
Neil Turton's avatar
Neil Turton committed
940

Neil Turton's avatar
Neil Turton committed
941
	BL	Stop
Neil Turton's avatar
Neil Turton committed
942

Neil Turton's avatar
Neil Turton committed
943
	MOV	R0, R2			; return the result
Neil Turton's avatar
Neil Turton committed
944

Neil Turton's avatar
Neil Turton committed
945
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
946

Kevin Bracey's avatar
Kevin Bracey committed
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996

; *****************************************************************************
;
;       ReadBlock - Read a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  All registers preserved
;


ReadBlock ROUT
        Push    "R0-R3,R14"
  [     E2ROMSupport
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamSize]
        |
        LDRB	R14, NVSize
        ]
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

        TEQ     R2, #0
        BEQ     %FT80

10      BL      ReadSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0-R3,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
Kevin Bracey's avatar
Kevin Bracey committed
997 998
 |
        SETV
Kevin Bracey's avatar
Kevin Bracey committed
999
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1000
        Pull    "R1-R3,PC"
Kevin Bracey's avatar
Kevin Bracey committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063

; *****************************************************************************
;
;       ReadSubBlock - Read a block of CMOS RAM specified by logical address.
;                      Assumes the address is valid, and will only read as much
;                      as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount read.
;
ReadSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100               ; [F0..100) -> [00..10) cached
        MOVLO   R3, #&100
        MOVLO   R4, #&00-&F0
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)
  [     CacheCMOSRAM
        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        STRB    R14, [R1], #1
        BLO     %BT12
Kevin Bracey's avatar
Kevin Bracey committed
1064
        Pull    "R3-R5,PC"              ; V will be clear
Kevin Bracey's avatar
Kevin Bracey committed
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

	BL	Start

	ADD	R0, R1, #1		; device address for read
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        BL      RXByte
        STRB    R0, [R1], #1
        SUBS    R5, R5, #1
        MOVNE   R0, #0                  ; not done - ACK byte
	MOVEQ   R0, #1                  ; done - no ACK
	BL	ClockData
        BNE     %BT20
Kevin Bracey's avatar
Kevin Bracey committed
1104
                                        ; V will be clear
Kevin Bracey's avatar
Kevin Bracey committed
1105 1106
	BL	Stop

Kevin Bracey's avatar
Kevin Bracey committed
1107
	Pull	"R0,R2,R3-R5,PC"
Kevin Bracey's avatar
Kevin Bracey committed
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252

; *****************************************************************************
;
;       ChecksumBlock - Checksum a block of CMOS RAM specified by logical address
;                       Assumes the address is valid.
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R1 incremented by sum of bytes in range
;


ChecksumBlock ROUT
        Push    "R0,R2,R14"

10      BL      ChecksumSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0,R2,PC"


; *****************************************************************************
;
;       ChecksumSubBlock - Checksum a block of CMOS RAM specified by logical address.
;                          Assumes the address is valid, and will only read as much
;                          as it can in a single IIC transaction. Skips over
;                          239 (the checksum byte itself), and 240-255 (OTP area).
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R0-R2 updated to reflect the data read.
;
ChecksumSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&EF                ; [C0..EF) -> [10..3F) cached
        MOVLO   R3, #&EF
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

;  [EF..100) -> not checksummed
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        SUB     R2, R2, R14
        Pull    "R3-R5,PC"


; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)

  [     CacheCMOSRAM
        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        ADD     R1, R1, R14
        BLO     %BT12
        Pull    "R3-R5,PC"
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

	BL	Start

	ADD	R0, R1, #1		; device address for read
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        BL      RXByte
        ADD     R1, R1, R0
        SUBS    R5, R5, #1
        MOVNE   R0, #0                  ; not done - ACK byte
	MOVEQ   R0, #1                  ; done - no ACK
	BL	ClockData
        BNE     %BT20

	BL	Stop

	Pull	"R0,R2,R3-R5,PC"

Neil Turton's avatar
Neil Turton committed
1253 1254
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1255 1256
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
1257
;
Neil Turton's avatar
Neil Turton committed
1258
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
1259
;
Neil Turton's avatar
Neil Turton committed
1260
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
1261
;
Neil Turton's avatar
Neil Turton committed
1262 1263 1264
;	C=0 => NVRam address is valid
;	 R0 = physical address within i2c device
;	 R1 = i2c device address for writing. Increment this device address
Kevin Bracey's avatar
Kevin Bracey committed
1265
;	      by 1 for reading. Bit 8 is set if device requires 2-byte physical address.
Neil Turton's avatar
Neil Turton committed
1266
;
Neil Turton's avatar
Neil Turton committed
1267 1268 1269 1270 1271 1272
;	C=1 => NVRam address is out of range of CMOS or E2ROM chips
;	 R0 preserved
;	 R1 preserved

  [	E2ROMSupport
GetI2CAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1273 1274 1275 1276 1277 1278 1279 1280 1281
	Push	"R14"
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0			; get no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	|
	LDRB	R14, NVSize
	]
	MOV	R14, R14, LSL #8
	CMP	R0, R14
Kevin Bracey's avatar
Kevin Bracey committed
1282
	Pull	"PC",CS 		; indicate invalid
Neil Turton's avatar
Neil Turton committed
1283

Kevin Bracey's avatar
Kevin Bracey committed
1284 1285 1286
; address is < end address -> is valid
	[ :LNOT: :DEF: TestHarness
	MOV	R1, #0
Neil Turton's avatar
Neil Turton committed
1287
	LDRB	R1, [R1, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
	|
	LDRB	R1, RTCFlag
	]
	TEQ	R1, #0
	MOVNE	R1, #RTCAddress
	[ :LNOT: :DEF: TestHarness
	LDREQB  R1, [R1, #NVRamBase]
	|
	LDREQB  R1, NVBase
	]

        CMP     R14, #2*1024            ; is the device bigger than 2K? If so, new addressing scheme
        ORRHI   R1, R1, #&100           ; set magic bit => 2 byte address
        BHI     %FT50
Neil Turton's avatar
Neil Turton committed
1302

Kevin Bracey's avatar
Kevin Bracey committed
1303 1304 1305 1306
	MOVS	R14, R0, LSR #8		; put top bits of physical address into device address
	ORRNE	R1, R1, R14, LSL #1
	ANDNE	R0, R0, #&FF		; and use address within 256 byte block
50
Kevin Bracey's avatar
Kevin Bracey committed
1307 1308
        CLC
	Pull	"PC"           		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1309

Neil Turton's avatar
Neil Turton committed
1310
  ]
Neil Turton's avatar
Neil Turton committed
1311 1312 1313


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1314 1315 1316 1317 1318
;
;	MangleCMOSAddress - Convert from logical to physical address
;
;	Doesn't check if address is larger than the amount of NVRam installed
;
Kevin Bracey's avatar
Kevin Bracey committed
1319
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1320
;
Kevin Bracey's avatar
Kevin Bracey committed
1321 1322
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1323
;
Kevin Bracey's avatar
Kevin Bracey committed
1324
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1325 1326
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1327

Neil Turton's avatar
Neil Turton committed
1328
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
 [ E2ROMSupport
	Push	"R14"
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0			; read no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	|
	LDRB	R14, NVSize
	]
	MOV	R14, R14, LSL #8
	CMP	R0, R14			; if >= end address then
	Pull	"R14"
Kevin Bracey's avatar
Kevin Bracey committed
1340
        MOVCS   PC, R14 		;    invalid (exit C set)
Kevin Bracey's avatar
Kevin Bracey committed
1341 1342

	CMP	R0, #&100		; if < end address && >= &100 then
Kevin Bracey's avatar
Kevin Bracey committed
1343 1344 1345
        BLO     %FT05
        CLC
        MOV     PC, R14                 ;    valid (no mungeing)
Kevin Bracey's avatar
Kevin Bracey committed
1346
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1347
05
Kevin Bracey's avatar
Kevin Bracey committed
1348 1349
	CMP	R0, #&F0		; if < &100 && >= &f0 then
        [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1350 1351 1352 1353
        BCC     %FT10
        SUB     R0, R0, #&F0            ;    map &F0->&FF to &00->0F for OTP section
        CLC
        MOV     PC, R14
Kevin Bracey's avatar
Kevin Bracey committed
1354
        |
Kevin Bracey's avatar
Kevin Bracey committed
1355
        MOVCS   PC, R14                 ;    invalid
Kevin Bracey's avatar
Kevin Bracey committed
1356
        ]
Kevin Bracey's avatar
Kevin Bracey committed
1357
10
Neil Turton's avatar
Neil Turton committed
1358 1359 1360
	ADD	R0, R0, #&40		; now in range &40..&13F
	CMP	R0, #&100
	SUBCS	R0, R0, #(&100-&10)	; now in range &40..&FF, &10..&3F
Kevin Bracey's avatar
Kevin Bracey committed
1361 1362
        CLC
        MOV     PC, R14                 ; valid
Neil Turton's avatar
Neil Turton committed
1363 1364 1365

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1366 1367
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1368 1369 1370 1371 1372
;       This routine performs MangleCMOSAddress inherently.
;
;       The checksum does not include physical locations &00->&0F, even
;       if they are OTP section (as this is usually used for a unique id
;       which will be different for every machine and can't be changed).
Neil Turton's avatar
Neil Turton committed
1373
;
Neil Turton's avatar
Neil Turton committed
1374
; in:	none
Neil Turton's avatar
Neil Turton committed
1375
;
Neil Turton's avatar
Neil Turton committed
1376 1377 1378
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1379 1380
;

Neil Turton's avatar
Neil Turton committed
1381
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1382

1383
ValChecksum	Entry "R1-R2"
Neil Turton's avatar
Neil Turton committed
1384

Kevin Bracey's avatar
Kevin Bracey committed
1385 1386
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1387
   [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1388 1389 1390 1391 1392 1393 1394
	[ :LNOT: :DEF: TestHarness
	MOV	R2, #0			; read number of 256 byte blocks and calculate end address
	LDRB	R2, [R2, #NVRamSize]
	|
	LDRB	R2, NVSize
	]
	MOV	R2, R2, LSL #8
Stewart Brodie's avatar
Stewart Brodie committed
1395 1396 1397
   |
	MOV	R2, #240
   ]
Kevin Bracey's avatar
Kevin Bracey committed
1398
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1399 1400

;
Kevin Bracey's avatar
Kevin Bracey committed
1401
; R1 contains the actual checksum. Compare it with the recorded checksum
Neil Turton's avatar
Neil Turton committed
1402
;
Kevin Bracey's avatar
Kevin Bracey committed
1403 1404 1405
40
	MOV	R0, #CheckSumCMOS
	BL	Read
Neil Turton's avatar
Neil Turton committed
1406
	AND	R2, R0, #&FF		; value from checksum location
Kevin Bracey's avatar
Kevin Bracey committed
1407
	AND	R0, R1, #&FF		; calculated value into R0
Neil Turton's avatar
Neil Turton committed
1408
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
1409

Neil Turton's avatar
Neil Turton committed
1410 1411
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
1412 1413 1414

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1415
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
1416
;
Neil Turton's avatar
Neil Turton committed
1417
; in:	none
Neil Turton's avatar
Neil Turton committed
1418
;
Neil Turton's avatar
Neil Turton committed
1419 1420
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1421 1422
;

Neil Turton's avatar
Neil Turton committed
1423
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1424

Neil Turton's avatar
Neil Turton committed
1425
MakeChecksum	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1426 1427 1428
	Push	"R1-R2,R14"
        MOV     R0, #0
        MOV     R1, #CMOSxseed
Stewart Brodie's avatar
Stewart Brodie committed
1429
  [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1430 1431 1432 1433 1434 1435 1436
	[ :LNOT: :DEF: TestHarness
	MOV	R2, #0
	LDRB	R2, [R2, #NVRamSize]
	|
	LDRB	R2, NVSize
	]
	MOV	R2, R2, LSL #8
Stewart Brodie's avatar
Stewart Brodie committed
1437 1438 1439
  |
	MOV	R2, #240
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1440
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1441 1442
	MOV	R0, #CheckSumCMOS
	BL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1443
	Pull	"R1-R2,PC"
Neil Turton's avatar
Neil Turton committed
1444
	]
Neil Turton's avatar
Neil Turton committed
1445

Kevin Bracey's avatar
Kevin Bracey committed
1446 1447
        LTORG

Neil Turton's avatar
Neil Turton committed
1448 1449
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1450
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1451
;
Neil Turton's avatar
Neil Turton committed
1452 1453 1454 1455 1456 1457 1458 1459 1460
; in:	UTC time:
;	R0 = hours
;	R1 = minutes
;	R2 = day of month
;	R3 = month
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1461
;
Neil Turton's avatar
Neil Turton committed
1462
;	Any of the above, if -1, will not be written to
Neil Turton's avatar
Neil Turton committed
1463 1464 1465
;

SetTime ROUT
Neil Turton's avatar
Neil Turton committed
1466
	Push	"R4, R14"		; save registers
Neil Turton's avatar
Neil Turton committed
1467

Stewart Brodie's avatar
Stewart Brodie committed
1468
 [ E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0
	LDRB	R14, [R14, #RTCFitted]
	|
	LDRB	R14, RTCFlag
	]

        TEQ     R14, #0
        BNE     %FT20

; no RTC - just set soft copy

 [ :LNOT: :DEF: TestHarness
        BL      RegToRealTime
 ]
        Pull    "R4, PC"
Stewart Brodie's avatar
Stewart Brodie committed
1485
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1486
20
Neil Turton's avatar
Neil Turton committed
1487 1488
; write year to CMOS RAM

Neil Turton's avatar
Neil Turton committed
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
	MOV	R4, R0			; save hours in R4

	Push	"R1"
	MOVS	R1, R5
	MOVPL	R0, #YearCMOS
	BLPL	Write
	MOVS	R1, R6
	MOVPL	R0, #YearCMOS+1
	BLPL	Write

	CMP	R4, #-1			; are we writing time ?
	Pull	"R1",EQ			; [no, then skip]
	BEQ	%FT30

	MOV	R0, #&01		; start at address 1
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	Pull	"R1"
	BL	StartTXPollAck
	MOV	R0, #&01		; offset 1
	BL	TXAck
	MOV	R0, R8			; centiseconds
	BL	HTBTA
	MOV	R0, R7			; seconds
	BL	HTBTA
	MOV	R0, R1			; minutes
	BL	HTBTA
	MOV	R0, R4			; hours
	BL	HTBTA
	BL	Stop

Neil Turton's avatar
Neil Turton committed
1524
30
Neil Turton's avatar
Neil Turton committed
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
	CMP	R2, #-1			; are we writing date ?
	BEQ	%FT40			; [no, then skip]

	MOV	R0, #&05		; start at address 5
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	BL	StartTXPollAck
	MOV	R0, #&05		; offset 5
	BL	TXAck
	MOV	R0, R2			; day of month
	BL	HexToBCD
	ORR	R0, R0, R5, LSL #6	; year in bits 6,7; day in bits 0..5
	BL	TXAck
	MOV	R0, R3			; months
	BL	HTBTA
	BL	Stop
Neil Turton's avatar
Neil Turton committed
1545

Neil Turton's avatar
Neil Turton committed
1546 1547 1548 1549 1550 1551
40
	MOV	R0, R4			; put hours back in R0
  [ :LNOT: :DEF: TestHarness
	BL	RTCToRealTime
  ]
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1552 1553 1554

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1555
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1556
;
Neil Turton's avatar
Neil Turton committed
1557
; in:	-
Neil Turton's avatar
Neil Turton committed
1558
;
Neil Turton's avatar
Neil Turton committed
1559 1560 1561 1562 1563 1564 1565 1566
; out:	R0 = hours
;	R1 = minutes
;	R2 = days
;	R3 = months
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1567 1568 1569
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
	Push	"R4, R14"

	MOV	R0, #&01		; start at address 1
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	BL	StartTXPollAck
	MOV	R0, #&01		; offset 1
	BL	TXAck
	BL	Start
    [	E2ROMSupport
	ADD	R0, R1, #1		; read address
    |
	MOV	R0, #(RTCAddress+1)	; read address
    ]
	BL	TXAck
	BL	RXByte
	BL	BCDToHex
	MOV	R8, R0			; centiseconds
	BL	CD0RBTH
	MOV	R7, R0			; seconds
	BL	CD0RBTH
	MOV	R1, R0			; minutes
	BL	CD0RBTH
	MOV	R4, R0			; hours
	BL	ClockData0
	BL	RXByte
	AND	R0, R0, #&3F		; day of month (clear year bits)
	BL	BCDToHex
	MOV	R2, R0
	BL	ClockData0
	BL	RXByte
	AND	R0, R0, #&1F		; month (clear day of week bits)
	BL	BCDToHex
	MOV	R3, R0
	MOV	R0, #1
	BL	ClockData
	BL	Stop

	MOV	R0, #YearCMOS
	BL	Read
	MOV	R5, R0			; year (lo)

	MOV	R0, #YearCMOS+1
	BL	Read
	MOV	R6, R0			; year (hi)

	MOV	R0, R4			; put hours in R0
Neil Turton's avatar
Neil Turton committed
1621 1622

; Ensure day/month are non-zero, fixes RTCToRealTime
Neil Turton's avatar
Neil Turton committed
1623 1624 1625 1626 1627
 [ {TRUE}				; LRust, fix RP-0370
	TEQ	R2, #0			; Valid day?
	MOVEQ	R2, #1			; No then force 1st
	TEQ	R3, #0			; Invalid month?
	MOVEQ	R3, #1			; Yes then force Jan
Neil Turton's avatar
Neil Turton committed
1628
 ]
Neil Turton's avatar
Neil Turton committed
1629
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1630 1631 1632

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1633 1634 1635 1636
;	InitCMOSCache - Initialise cache of CMOS RAM

  [	CacheCMOSRAM

1637
InitCMOSCache	Entry "r0-r6"
Neil Turton's avatar
Neil Turton committed
1638 1639
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
; Need to set the slowest speed so we can probe

        MOV     R2, #0
        MOV     R3, #10         ; Default speed setting (5s delays)
	[ :LNOT: :DEF: TestHarness
        STRB    R3, [R2, #NVRamSpeed]
	|
        STRB    R3, NVSpeed
	]

;	First determine what hardware we've got fitted, R4 holds the number of
Neil Turton's avatar
Neil Turton committed
1651 1652 1653 1654 1655
;	256 byte blocks that we've found

	; Have we got an RTC ?
	MOV	R0, #RTCAddress
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1656 1657 1658 1659 1660 1661 1662
	MOVVS	R4, #0
	MOVVC	R4, #1
	[ :LNOT: :DEF: TestHarness
	STRB	R4, [R2, #RTCFitted]
	|
	STRB	R4, RTCFlag
	]
Robert Catherall's avatar
Robert Catherall committed
1663
        MOV     R3, #10         ; assume 100kHz to start with
Kevin Bracey's avatar
Kevin Bracey committed
1664
        MOV     R5, #4          ; assume 16 byte page size to start with
1665
        MOV     R6, #0          ; assume not protected
Kevin Bracey's avatar
Kevin Bracey committed
1666 1667 1668 1669 1670 1671 1672 1673

; Have we got a 2K E ?
        MOV     r1, #E2ROMAddress2K
	MOV	r0, #(E2ROMAddress2K+14)
	BL	DummyAccess
	MOVVC	R4, #8
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
	BVC	%FT5
Neil Turton's avatar
Neil Turton committed
1674 1675

; Have we got a 1K E ?
Kevin Bracey's avatar
Kevin Bracey committed
1676
        MOV     r1, #E2ROMAddress
Neil Turton's avatar
Neil Turton committed
1677 1678
	MOV	r0, #(E2ROMAddress+6)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1679
	MOVVC	R4, #4
Neil Turton's avatar
Neil Turton committed
1680 1681 1682 1683 1684
	BVC	%FT5

; Have we got 512 bytes of E ?
	MOV	r0, #(E2ROMAddress+2)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1685
	MOVVC	R4, #2
Neil Turton's avatar
Neil Turton committed
1686 1687
	BVC	%FT5

Kevin Bracey's avatar
Kevin Bracey committed
1688 1689 1690
; Have we got a 16K device ? (Note that this probe would make a 24C08 device respond -
; but if we've gotten this far it would have to be a < 512 byte version; we've never
; used such a device).
Neil Turton's avatar
Neil Turton committed
1691

Kevin Bracey's avatar
Kevin Bracey committed
1692 1693 1694 1695 1696 1697
        MOV     r1, #E2ROMAddress16K
	MOV	r0, #E2ROMAddress16K
	BL	DummyAccess
	MOVVC	R4, #64
        MOVVC   R5, #6          ; 64 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
1698 1699
        BVC     %FT5

1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
; Have we got a 4K device?

        MOV     r1, #E2ROMAddress4K
	MOV	r0, #E2ROMAddress4K
	BL	DummyAccess
	MOVVC	R4, #16
        MOVVC   R6, #12         ; Only bottom 3K writable
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
        BVC     %FT5

1711 1712 1713 1714 1715 1716
; Have we got an 8K device?

        MOV     r1, #E2ROMAddress8K
	MOV	r0, #E2ROMAddress8K
	BL	DummyAccess
	MOVVC	R4, #32
1717
        MOVVC   R6, #24         ; Only bottom 6K writable
1718 1719
        MOVVC   R5, #5          ; 32 byte page size
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
Robert Catherall's avatar
Robert Catherall committed
1720 1721 1722
        BVC     %FT5

; Have we got a 32K device?
1723

Robert Catherall's avatar
Robert Catherall committed
1724 1725 1726 1727 1728 1729 1730 1731 1732
        MOV     r1, #E2ROMAddress32K
        MOV     r0, #E2ROMAddress32K
        BL      DummyAccess
        MOVVC   R4, #128        ; 128,120,6,1
        MOVVC   R6, #120        ; Only bottom 30K writable
        MOVVC   R5, #6          ; 64 byte page size
        MOVVC   R3, #1          ; Hyper-fast speed setting (0.5s delays - 1MHz part)

        MOVVS   R1, #RTCAddress
Kevin Bracey's avatar
Kevin Bracey committed
1733 1734 1735
        MOVVS   R5, #8          ; 256 byte page size for CMOS

5
Neil Turton's avatar
Neil Turton committed
1736
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1737 1738 1739 1740
	[ :LNOT: :DEF: TestHarness
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
1741 1742 1743
        TEQ     R6, #0
        MOVEQ   R6, R4
        STRB    R6, [R2, #NVRamWriteSize]
Robert Catherall's avatar
Robert Catherall committed
1744 1745 1746

        CMP     R3, #I2Cticks   ; clamp speed to maximum bus speed
        MOVLO   R3, #I2Cticks
Kevin Bracey's avatar
Kevin Bracey committed
1747
        STRB    R3, [R2, #NVRamSpeed]
Robert Catherall's avatar
Robert Catherall committed
1748

Kevin Bracey's avatar
Kevin Bracey committed
1749 1750 1751 1752 1753 1754 1755 1756
	LDR	R3, =CMOSRAMCache
	|
	STRB    R1, NVBase
	STRB	R4, NVSize
        STRB    R5, NVPageSize
        STRB    R3, NVSpeed
	ADR	R3, i2cWorkSpace
	]
Neil Turton's avatar
Neil Turton committed
1757 1758

	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1759 1760 1761 1762 1763 1764 1765 1766 1767
        TEQ     R4, #8                  ; check for 2K part
	MOVNE	r0, #&00		; if not, then start at 0 anyway and read non-OTP data into location 0..15
        BNE     %FT07
	BL	ReadOTPArea
	MOV	r0, #&10		; read rest of it from 16 onwards
07
        BL      GetI2CAddress           ; and convert to device address and offset
        MOV     R2, R0                  ; save the offset
        MOV     R4, #&100               ; stop at &100
Neil Turton's avatar
Neil Turton committed
1768 1769 1770
    |
	MOV	R1, #RTCAddress
	MOV	R2, #&10
Kevin Bracey's avatar
Kevin Bracey committed
1771 1772 1773 1774 1775 1776
	MOV	R4, #&100		; stop at address &100
        [	:LNOT: :DEF: TestHarness
	LDR	R3, =CMOSRAMCache
        |
	ADR	R3, i2cWorkSpace
        ]
Neil Turton's avatar
Neil Turton committed
1777
    ]
Kevin Bracey's avatar
Kevin Bracey committed
1778
09
Neil Turton's avatar
Neil Turton committed
1779
	BL	Start
Neil Turton's avatar
Neil Turton committed
1780

Neil Turton's avatar
Neil Turton committed
1781 1782
	MOV	R0, R1			; write address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1783

Kevin Bracey's avatar
Kevin Bracey committed
1784 1785 1786 1787 1788
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; memory word address (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; memory word address (LSB)
Neil Turton's avatar
Neil Turton committed
1789
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1790

Neil Turton's avatar
Neil Turton committed
1791
	BL	Start
Neil Turton's avatar
Neil Turton committed
1792

Kevin Bracey's avatar
Kevin Bracey committed
1793
	ORR	R0, R1, #1		; read address
Neil Turton's avatar
Neil Turton committed
1794
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1795 1796

10
Neil Turton's avatar
Neil Turton committed
1797 1798 1799
	BL	RXByte			; returned in R0
	STRB	R0, [R3, R2]
	ADD	R2, R2, #1		; increment R2 to phys. address
Kevin Bracey's avatar
Kevin Bracey committed
1800 1801
	CMP	R2, R4			; stop when we hit end address
	BGE	%FT20
Neil Turton's avatar
Neil Turton committed
1802

Kevin Bracey's avatar
Kevin Bracey committed
1803 1804 1805
	TST	R2, #&FF		; still in same 256 byte block?
	MOVNE	R0, #0			; yes => not done .. ACK that byte
	MOVEQ	R0, #1			; no => finish off reading block
Neil Turton's avatar
Neil Turton committed
1806
	BL	ClockData
Kevin Bracey's avatar
Kevin Bracey committed
1807 1808 1809 1810 1811 1812 1813 1814
	BNE	%BT10			; yes => continue reading

   [ E2ROMSupport
	BL	Stop
	MOV	R0, R2			; in next 256 byte block so get device + address
	BL	GetI2CAddress
	B	%BT09			; and start next block
   ]
Neil Turton's avatar
Neil Turton committed
1815
20
Neil Turton's avatar
Neil Turton committed
1816 1817 1818
	MOV	R0, #1			; finish off reading block
	BL	ClockData
	BL	Stop
Kevin Bracey's avatar
Kevin Bracey committed
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853

   [ E2ROMSupport
        TEQ     R4, #&100               ; have we reached the end?
        EXIT    EQ                      ; exit if so

        MOV     R0, R4                  ; start next block from R4
        MOV     R4, #&100               ; stop at &100
        BL      GetI2CAddress           ; convert to device address and offset
        MOV     R2, R0                  ; save the offset
        B       %BT09                   ; and go round again
   |
	EXIT
   ]

   [ E2ROMSupport
ReadOTPArea Entry
	BL	Start
	MOV	r0, #E2ROMAddress2K_OTP
	BL	TXAck
	MOV	r0, #0				; OTP memory word address
	BL	TXAck
	BL	Start
	MOV	r0, #E2ROMAddress2K_OTP + 1	; switch to read
	BL	TXAck
	MOV	r2, #0
10
	BL	RXByte
	STRB	r0, [r3, r2]
	ADD	r2, r2, #1
	TEQ	r2, #16
	MOVNE	r0, #0				; not done, so clock zero
	MOVEQ	r0, #1
	BL	ClockData
	BNE	%BT10
	BL	Stop
Neil Turton's avatar
Neil Turton committed
1854
	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1855
   ]
Neil Turton's avatar
Neil Turton committed
1856

Neil Turton's avatar
Neil Turton committed
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
  ]


; *****************************************************************************
;
;	DummyAccess - do a dummy access of the specified device to find out
;	              if it is present
;
; in:	R0 = Write address of device
;
; out:	All registers preserved
;	V=0 => device is present
;	V=1 => device is not present

; Have we got an RTC ? do a read from location 0 to find out

  [ E2ROMSupport
1874
DummyAccess	Entry
Neil Turton's avatar
Neil Turton committed
1875 1876 1877 1878 1879 1880 1881

	BL	Start
	BL	TXAck			; do write and set V if no ack
	BL	Stop			; Doesn't change the PSR
	EXIT				; Exit with V set appropriately
  ]

Kevin Bracey's avatar
Kevin Bracey committed
1882 1883 1884 1885 1886 1887 1888
; *****************************************************************************
;
;       SWI OS_NVMemory
;
; in:   R0 = reason code
;

1889
NVMemorySWI     Entry
Kevin Bracey's avatar
Kevin Bracey committed
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
        BL      NVMemorySub
        PullEnv
        ORRVS   LR, LR, #V_bit
        ExitSWIHandler

NVMemorySub
        CMP     R0, #4
        ADDLS   PC, PC, R0, LSL #2
        B       NVMemory_Unknown
        B       NVMemory_Size
        B       NVMemory_Read
        B       NVMemory_Write
        B       NVMemory_ReadBlock
        B       NVMemory_WriteBlock

NVMemory_Unknown
        ADRL    R0, ErrorBlock_HeapBadReason
 [ International
        Push    LR
        BL      TranslateError
        Pull    LR
 ]
Kevin Bracey's avatar
Kevin Bracey committed
1912
        RETURNVS
Kevin Bracey's avatar
Kevin Bracey committed
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927

; -----------------------------------------------------------------------------
; OS_NVMemory 0 - find NV memory size
;
; in:   R0 = 0
;
; out:  R1 = NV memory size in bytes
;
NVMemory_Size
  [     E2ROMSupport
        LDRB    R1, [R0, #NVRamSize]
        MOV     R1, R1, LSL #8
  |
        MOV     R1, #240
  ]
Kevin Bracey's avatar
Kevin Bracey committed
1928
        MOV     PC, LR
Kevin Bracey's avatar
Kevin Bracey committed
1929 1930 1931 1932 1933 1934 1935 1936 1937 1938

; -----------------------------------------------------------------------------
; OS_NVMemory 1 - read a byte
;
; in:   R0 = 1
;       R1 = location
;
; out:  R2 = value
;
NVMemory_Read
1939 1940
        Entry   "R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1941
        BIC     R0, R4, #I32_bit
1942
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1943 1944 1945 1946 1947
        MOV     R0, R1
        BL      ReadWithError
        MOVVC   R2, R0
        MOVVC   R0, #1          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1948
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 2 - write a byte
;
; in:   R0 = 1
;       R1 = location
;       R2 = value
;
NVMemory_Write ROUT
        [ ProtectStationID
        TEQ     R1, #0          ; just ignore writes to byte 0
        MOVEQ   PC, R14
        ]
1963 1964
        Entry   "R1,R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1965
        BIC     R0, R4, #I32_bit
1966
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1967 1968 1969 1970 1971
        MOV     R0, R1
        MOV     R1, R2
        BL      WriteWithError
        MOVVC   R0, #2          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1972
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 3 - read a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_ReadBlock
1984
        Entry   "R1-R4"
Kevin Bracey's avatar
Kevin Bracey committed
1985
        MOV     R4, PC
1986
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
1987
        BIC     R0, R4, #I32_bit
1988
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
1989 1990 1991 1992 1993 1994
        MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      ReadBlock
        MOVVC   R0, #3          ; must preserve R0
        ORRVS   R4, R4, #V_bit
1995
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 4 - write a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_WriteBlock ROUT
2007 2008
        Entry   "R1-R4"
        MRS     R4, CPSR
Kevin Bracey's avatar
Kevin Bracey committed
2009
        BIC     R0, R4, #I32_bit
2010
        MSR     CPSR_c, R0      ; enable interrupts - this may take some time
Kevin Bracey's avatar
Kevin Bracey committed
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
        [ ProtectStationID
        TEQ     R1, #0
        BNE     %FT10
        ADD     R1, R1, #1
        ADD     R2, R2, #1
        TEQ     R3, #0
        SUBNE   R3, R3, #1      ; steer clear of station ID
        ]
10      MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      WriteBlock
        MOVVC   R0, #4          ; must preserve R0
        ORRVS   R4, R4, #V_bit
2025
        MSR     CPSR_cf, R4     ; restore interrupt state
Kevin Bracey's avatar
Kevin Bracey committed
2026 2027
        EXIT

Neil Turton's avatar
Neil Turton committed
2028
	END