; Copyright 1999 Element 14 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. ; ; This file handles the programming of flash devices in ROM bank 0 with ; a ROM image transferred via the parallel port. This is for development ; purposes only, and is only likely to work on the system for which it was ; designed. ; Flash Memory Settings FR_FlashBase * &00000000 FR_DeviceBufferSize * 32 ; 28F640J5 has 32 byte buffer FR_DeviceBlockSizeBits * 17 ; 28F640J5 has 128KB blocks FR_DeviceBlocks * 64 ; 64 blocks in a 28F640J5 FR_BufferSize * FR_DeviceBufferSize*2 ; 2 devices FR_BlockSizeBits * FR_DeviceBlockSizeBits+1 ; 2 devices FR_BlockSize * 1 :SHL: FR_BlockSizeBits ; 256KB FR_FlashSize * FR_BlockSize*FR_DeviceBlocks ; 16MB ; Sizes of things in memory FR_StackSize * 1024 FR_RAMCodeSize * 4096 FR_ScreenSize * 472*1024 ; Addresses of where we put things in memory FR_PageTableBaseAddr * DRAM0PhysRam FR_StackBase * FR_PageTableBaseAddr+16*1024+FR_StackSize FR_RAMCodeAddr * FR_StackBase FR_ScreenBase * (FR_RAMCodeAddr+FR_RAMCodeSize+15):AND::NOT:&F FR_TransferBuffAddr * FR_ScreenBase ; Combo chip addresses FR_ComboCfgBase * &03010000 + &3F0*4 FR_PPortBase * &03010000 + &278*4 FR_ECRPortBase * FR_PPortBase + &402*4 ; On entry, R11->IOMD ; Will either reprogram the flash, or branch back to 0. ; We're in SVC32 mode with the MMU off, by the way. ASSERT IOMD_C_FrontPanelButton <> 0 ConsiderFlashROM LDRB R0,[R11,#IOMD_CLINES] TST R0,#IOMD_C_FrontPanelButton MOVNE PC,#0 FlashROM ; Switch CPU to 32-bit mode MOV R0,#MMUC_L :OR: MMUC_D :OR: MMUC_P ; Set PROG32 and DATA32 ARM_write_control R0 msr ,CPSR_c,#I32_bit :OR: F32_bit :OR: SVC32_mode ; Initialise various CPU control registers MOV R0,#IOMD_ROMCR_NSTicks_5 :OR: IOMD_ROMCR_HalfSpeed :OR: IOMD_ROMCR_32bit STRB R0,[R11,#IOMD_ROMCR0] MOV R0,#IOMD_CLKCTL_CpuclkHalf :OR: IOMD_CLKCTL_MemclkNormal :OR: IOMD_CLKCTL_IOclkNormal STRB R0,[R11,#IOMD_CLKCTL] MOV R0,#IOMD_DRAMWID_RASPre_3 :OR: IOMD_DRAMWID_RASCAS_3 :OR: IOMD_DRAMWID_EDO_Enable :OR: IOMD_DRAMWID_DRAM_32bit STRB R0,[R11,#IOMD_DRAMWID] MOV R0,#IOMD_IOTCR_Combo_TypeB :OR: IOMD_IOTCR_Network_TypeC STRB R0,[R11,#IOMD_IOTCR] MOV R0,#1 ; Card 0 type C, the rest type A STRB R0,[R11,#IOMD_ECTCR] MOV R0,#IOMD_ASTCR_WaitStates STRB R0,[R11,#IOMD_ASTCR] MOV R0,#IOMD_C_ReadMask :OR: IOMD_C_ROMCardVpp ; Green LED on STRB R0,[R11,#IOMD_CLINES] ; Main setup MOV R10,#VIDC ; Keep R10 pointing to video registers from here on BL FR_InitVideo BL FR_FillScreen BL FR_SetPageTable BL FR_SetMMU BL FR_InitParallel ; Sets R9 to parallel base address - keep it this way ; Copy the rest of code to RAM and jump to it ADR R0,FR_CopyBlockStart LDR R1,=FR_RAMCodeAddr MOV LR,R1 LDR R2,=FR_RAMCodeEnd - FR_CopyBlockStart 01 LDR R3,[R0],#4 STR R3,[R1],#4 SUBS R2,R2,#4 BNE %BT01 MOV PC,LR FR_InitVideo ROUT ; Set DMA registers LDR R1,=FR_ScreenBase ADD R2,R1,#FR_ScreenSize SUB R2,R2,#16 STR R1,[R11,#IOMD_VIDSTART] STR R2,[R11,#IOMD_VIDEND] STR R1,[R11,#IOMD_VIDINIT] STR R1,[R11,#IOMD_VIDCUR] STR R1,[R11,#IOMD_CURSINIT] STR R1,[R11,#IOMD_CURSCUR] MOV R1,#0 STR R1,[R11,#IOMD_VIDINITB] MOV R1,#IOMD_VIDCR_DRAMMode :OR: IOMD_VIDCR_Enable STRB R1,[R11,#IOMD_VIDCR] ; Set video registers ADR R1,FR_InitVidRegs MOV R2,#(FR_InitVidRegsEnd-FR_InitVidRegs) 02 LDR R3,[R1],#4 STR R3,[R10] SUBS R2,R2,#4 BNE %BT02 ; Set grey palette MOV R1,#&10000000 STR R1,[R10] MOV R1,#0 MOV R2,#&000001 ORR R2,R2,#&000100 ORR R2,R2,#&010000 MOV R3,#256 03 STR R1,[R10] ADD R1,R1,R2 SUBS R3,R3,#1 BNE %BT03 MOV PC,LR ; Frequency synthesizer register settings FR_ModR * 8 FR_ModV * 9 ; 36 MHz ; Video control register settings FR_FIFO * 3 ; 12 loads FR_BPP * 3 ; 8bpp FR_PixelRate * 0 ; CK/1 FR_ClockSource * 0 ; VCLK ; Horizontal timings FR_HSync * 72 FR_HBPch * 86 FR_HLBdr * 24 FR_HDisp * 800 FR_HRBdr * 24 FR_HFPch * 18 FR_HDWR * FR_HDisp / 4 ; Vertical timings FR_VSync * 2 FR_VBPch * 22 FR_VTBdr * 0 FR_VDisp * 600 FR_VBBdr * 0 FR_VFPch * 1 FR_InitVidRegs ROUT DCD &E0000000+(FR_FIFO:SHL:8)+(FR_BPP:SHL:5)+(FR_PixelRate:SHL:2)+FR_ClockSource DCD &D0000000+&C288 DCD &80000000+FR_HSync+FR_HBPch+FR_HLBdr+FR_HDisp+FR_HRBdr+FR_HFPch-8 DCD &81000000+FR_HSync-8 DCD &82000000+FR_HSync+FR_HBPch-12 DCD &83000000+FR_HSync+FR_HBPch+FR_HLBdr-18 DCD &84000000+FR_HSync+FR_HBPch+FR_HLBdr+FR_HDisp-18 DCD &85000000+FR_HSync+FR_HBPch+FR_HLBdr+FR_HDisp+FR_HRBdr-12 DCD &90000000+FR_VSync+FR_VBPch+FR_VTBdr+FR_VDisp+FR_VBBdr+FR_VFPch-2 DCD &91000000+FR_VSync-2 DCD &92000000+FR_VSync+FR_VBPch-1 DCD &93000000+FR_VSync+FR_VBPch+FR_VTBdr-1 DCD &94000000+FR_VSync+FR_VBPch+FR_VTBdr+FR_VDisp-1 DCD &95000000+FR_VSync+FR_VBPch+FR_VTBdr+FR_VDisp+FR_VBBdr-1 DCD &40008000 DCD &C0000000+(1:SHL:12)+3 DCD &D0000000+&C080+((FR_ModV-1):SHL:8)+(FR_ModR-1) DCD &D0000000+((FR_ModV-1):SHL:8)+(FR_ModR-1) DCD &F0000000+(1:SHL:16)+(1:SHL:12)+FR_HDWR DCD &B1000000 FR_InitVidRegsEnd FR_FillScreen ROUT LDR R1,=FR_ScreenBase MOV R2,#((256:SHL:16)/600):AND:&00FF ORR R2,R2,#((256:SHL:16)/600):AND:&FF00 MOV R3,R2 MOV R4,#FR_VDisp 01 MOV R5,#FR_HDisp MOV R0,R3,LSR #16 ORR R0,R0,R0,LSL #8 ORR R0,R0,R0,LSL #16 02 STR R0,[R1],#4 SUBS R5,R5,#4 BNE %BT02 ADD R3,R3,R2 SUBS R4,R4,#1 BNE %BT01 MOV PC,LR ;Make a page table that basically gives flat addressing with the C and B bits ;set approriately for the RAM areas. The RAM areas are set with both the C and B ;bits on, and all other areas have both C and B off. The flash area must not ;be made cacheable, or programming won't work. ;On exit ; r0-r4 corrupted FR_SetPageTable ROUT MOV R1,#FR_PageTableBaseAddr MOV R2,#0 ; Address MOV R4,#L1_U + L1_Section ORR R4,R4,#AP_Full * L1_APMult 01 BICS R3,R2,#&E0000000 ; Repeats at &00000000, &20000000, &4000000, etc. BICEQ R4,R4,#L1_C + L1_B ; Clear B and C bits from start of ROM area CMP R3,#&10000000 ORREQ R4,R4,#L1_C + L1_B ; Set B and C bits (RAM area cacheable and bufferable) ORR R0,R3,R4 STR R0,[R1],#4 ADDS R2,R2,#1024*1024 BCC %BT01 MOV PC,LR FR_SetMMU ROUT MOV R0,#FR_PageTableBaseAddr ARM_MMU_transbase R0 MVN R0,#0 ; Full access to all domains ARM_MMU_domain R0 MOV R0,#MMUC_L + MMUC_D + MMUC_P + MMUC_W + MMUC_C + MMUC_M ARM_write_control R0 ; Enable write buffer, cache and MMU MOV PC,LR FR_InitParallel ROUT LDR R1,=FR_ComboCfgBase ; Enter config mode MOV R0,#&55 STRB R0,[R1] STRB R0,[R1] ; Write CR0 MOV R0,#0 STRB R0,[R1] MOV R0,#&22 STRB R0,[R1,#4] ; CR0=&22 (FDC, IDE off) ; Write CR1 MOV R0,#1 STRB R0,[R1] MOV R0,#&97 STRB R0,[R1,#4] ; CR1=&97 (Parallel port on, extended) ; Write CR4 MOV R0,#4 STRB R0,[R1] MOV R0,#&03 ; CR4=&03 (ECP & EPP mode) STRB R0,[R1,#4] ; Write ECR MOV R0,#&34 ; PS/2 Parallel Port mode, DMA off, interrupts off LDR R9,=FR_ECRPortBase STRB R0,[R9] ; Exit config mode MOV R0,#&AA STRB R0,[R1] ; Initialise parallel port LDR R9,=FR_PPortBase ; Clear nSTROBE bit (puts nACK high) and clear nSLCTIN bit (puts BUSY high) to ; indicate we are busy and not accepting data. MOV R0,#&20 ; Input, IRQ off, nSLCTIN clear, nSTROBE clear STRB R0,[R9,#8] ; Keep parallel port base address in R9 from here on MOV PC,LR LTORG FR_CopyBlockStart ; Dont use literals from here on in - the assembler's liable to pull them ; the non-RAM stuff above. ; Code from here on gets copied to RAM (at FR_RAMCodeAddr) and run from there. FR_RAMCodeStart MOV R0,#IOMD_C_ReadMask :OR: IOMD_C_FrontPanelLED :OR: IOMD_C_ROMCardVpp STRB R0,[R11,#IOMD_CLINES] ; Red LED on LDR R13,FR_StackBaseVal FR_LoopForever MOV R0,#FR_WaitCmdState-FR_BorderStateTable BL FR_ShowStateBorder ; Wait for a command header BL FR_ParallelRead CMP R0,#'M' BNE FR_LoopForever BL FR_ParallelRead CMP R0,#'P' BNE FR_LoopForever BL FR_ParallelRead CMP R0,#'T' BNE FR_LoopForever BL FR_ParallelRead CMP R0,#'!' BNE FR_LoopForever BL FR_ParallelRead CMP R0,#'P' BEQ FR_BeginProgram CMP R0,#'V' BEQ FR_BeginVerify B FR_LoopForever FR_BeginProgram ROUT MOV R0,#FR_BeginProgramState-FR_BorderStateTable BL FR_ShowStateBorder ; Read in parameters BL FR_ReadOffsetAndCount ; Ready to go - first make the ROM area writable BL FR_MakeROM0Writable 01 ; Begin erasing the block MOV R0,R7 BL FR_StartErase ; Read the block data into the buffer BL FR_ReadBlockIntoBuffer ; Data read in OK - wait for erase to finish BL FR_CheckErase ; Now write block MOV R0,#FR_WriteBlockState-FR_BorderStateTable BL FR_ShowStateBorder MOV R0,R7 LDR R1,FR_TransferBuffVal BL FR_DoWriteBlock ; Verify the block BL FR_ResetToReadArray MOV R0,#FR_VerifyBlockState-FR_BorderStateTable BL FR_ShowStateBorder MOV R0,R7 LDR R1,FR_TransferBuffVal BL FR_VerifyBlock ; Block done, on to the next ADD R7,R7,#FR_BlockSize SUBS R8,R8,#1 BNE %BT01 ; All finished - make ROM area read-only BL FR_MakeROM0ReadOnly B FR_LoopForever FR_BeginVerify ROUT MOV R0,#FR_BeginVerifyState-FR_BorderStateTable BL FR_ShowStateBorder ; Read in parameters BL FR_ReadOffsetAndCount 01 ; Read the block data into the buffer BL FR_ReadBlockIntoBuffer ; Data read in OK - now verify MOV R0,#FR_VerifyBlockState-FR_BorderStateTable BL FR_ShowStateBorder MOV R0,R7 LDR R1,FR_TransferBuffVal BL FR_VerifyBlock ; Block done, on to the next ADD R7,R7,#FR_BlockSize SUBS R8,R8,#1 BNE %BT01 ; All done B FR_LoopForever FR_ReadOffsetAndCount ROUT ;Called by the program and verify commands to read their parameters (offset ;and count) from the parallel port. ;On exit ; r7 = Initial offset in Flash ROM area ; r8 = Block count ; r0-r3 corrupted STMFD R13!,{LR} ; Next incoming word is the block offset to start from BL FR_ParallelReadWord MOV R7,R0 ; Check the offset is valid CMP R7,#FR_FlashSize BHS FR_OffsetError MOVS R0,R7,LSL#(32-FR_BlockSizeBits) ; The offset within the block should be 0 BNE FR_OffsetError ; Next incoming byte is the number of blocks BL FR_ParallelRead MOVS R8,R0 BEQ FR_BlockCountError ADD R0,R7,R8,LSL #FR_BlockSizeBits CMP R0,#FR_FlashSize BHI FR_BlockCountError ; Turn the offset into a real address ADD R7,R7,#FR_FlashBase LDMFD R13!,{PC} FR_ReadBlockIntoBuffer ROUT ;Read a block of data from the parallel port into the transfer buffer ;Corrupts r0-r6 STMFD R13!,{LR} MOV R0,#FR_ReadBlockState-FR_BorderStateTable BL FR_ShowStateBorder MOV R6,#FR_BlockSize LDR R5,FR_TransferBuffVal MOV R4,#0 ; Checksum 01 BL FR_ParallelReadWord STR R0,[R5],#4 ADD R4,R4,R0 SUBS R6,R6,#4 BNE %BT01 ; Next word is the checksum BL FR_ParallelReadWord CMP R0,R4 BNE FR_ChecksumError LDMFD R13!,{PC} FR_ChecksumError ROUT MOV R0,#FR_ChecksumErrorState-FR_BorderStateTable B FR_Error FR_OffsetError MOV R0,#FR_OffsetErrorState-FR_BorderStateTable B FR_Error FR_BlockCountError MOV R0,#FR_BlockCountErrorState-FR_BorderStateTable FR_Error BL FR_ShowStateBorder ; Wait for front panel button to be pressed 01 LDRB R0,[R11,#IOMD_CLINES] TST R0,#IOMD_C_FrontPanelButton BNE %BT01 ; Start again (note this also resets the stack pointer) B FR_RAMCodeStart FR_ShowStateBorder STMFD R13!,{R1} ADR R1,FR_BorderStateTable LDR R0,[R1,R0] STR R0,[R10] LDMFD R13!,{R1} MOV PC,LR FR_BorderStateTable FR_WaitCmdState DCD &40FF0000 ;Waiting for command - Blue FR_BeginProgramState DCD &40808080 ;Begin Program command - Grey FR_BeginVerifyState DCD &40404040 ;Begin Verify command - Dark grey FR_ReadBlockState DCD &40FFFF00 ;Reading block - Cyan FR_WriteBlockState DCD &4000FF00 ;Writing block - Green FR_VerifyBlockState DCD &40FFFFFF ;Verifying block - White FR_OffsetErrorState DCD &400000FF ;Offset error - Red FR_BlockCountErrorState DCD &4000FFFF ;Block count error - Yellow FR_ChecksumErrorState DCD &40FF00FF ;Checksum error - Magenta FR_EraseErrorState DCD &40808000 ;Erase error - Dark Cyan FR_VoltageRangeErrorState DCD &40000080 ;Voltage range error - Dark Red FR_DeviceProtectErrorState DCD &40800000 ;Device protect error - Dark Blue FR_ProgramErrorState DCD &40008080 ;Program error - Dark Yellow FR_VerifyErrorState DCD &4000BBFF ;Verify error - Orange FR_ParallelRead ROUT ;Read a byte of data from the parallel port ;On entry ; r9 = Parallel port base address ;On exit ; r0 = byte read ; r1 corrupted ;Set nSLCTIN bit (puts BUSY low) and clear nSTROBE bit (puts nACK high), ;to indicate that we are ready to receive data MOV R0,#&28 ; Input, IRQ off, BUSY low, nACK high STRB R0,[R9,#8] ;Now wait until nACK bit (nSTROBE) goes low, meaning a byte is ready to be read 01 LDRB R0,[R9,#4] TST R0,#&40 BNE %BT01 ;Read the byte LDRB R0,[R9] ;Set nSTROBE bit (puts nACK low) to indicate we read the byte, and ;clear nSLCTIN bit (puts BUSY high) to indicate we are busy and won't accept ;any more data MOV R1,#&21 ; Input, IRQ off, BUSY high, nACK low STRB R1,[R9,#8] ;Make sure nACK bit (nSTROBE) has returned high 02 LDRB R1,[R9,#4] TST R1,#&40 BEQ %BT02 ;Finish nAck pulse by clearing nSTROBE bit (puts nACK high). Keep BUSY high MOV R1,#&20 ; Input, IRQ off, BUSY high, nACK high STRB R1,[R9,#8] MOV pc,lr FR_ParallelReadWord ROUT ;Read a word of data from the parallel port ;On entry ; r9 = Parallel port base address ;On exit ; r0 = word read ; r1-r3 corrupted MOV R3,LR BL FR_ParallelRead MOV R2,R0 BL FR_ParallelRead ORR R2,R2,R0,LSL #8 BL FR_ParallelRead ORR R2,R2,R0,LSL #16 BL FR_ParallelRead ORR R0,R2,R0,LSL #24 MOV PC,R3 FR_MakeROM0Writable STMFD R13!,{R0} LDRB R0,[R11,#IOMD_ROMCR0] ORR R0,R0,#&80 STRB R0,[R11,#IOMD_ROMCR0] LDMFD R13!,{R0} MOV PC,LR FR_MakeROM0ReadOnly STMFD R13!,{R0} LDRB R0,[R11,#IOMD_ROMCR0] BIC R0,R0,#&80 STRB R0,[R11,#IOMD_ROMCR0] LDMFD R13!,{R0} MOV PC,LR FR_ResetToReadArray ROUT ;Reset the flash devices to Read Array mode STMFD R13!,{R0,R1} MOV R0,#FR_FlashBase MOV R1,#&FF ORR R1,R1,R1,LSL #8 STR R1,[R0] ; Write the Read Array command (&FF) to both devices LDMFD R13,{R0,R1} MOV PC,LR FR_StartErase ROUT ;Start to erase a block (256KB) of flash memory ;On entry ; r0=Block Address (real memory address) STMFD R13!,{R1} MOV R1,#&20 ORR R1,R1,R1,LSL #8 STR R1,[R0] ; Write the Block Erase command (&20) to both devices MOV R1,#&D0 ORR R1,R1,R1,LSL #8 STR R1,[R0] ; Write the Confirm command (&D0) to both devices LDMFD R13!,{R1} MOV PC,LR FR_CheckErase ROUT ;Wait for erase to finish STMFD R13!,{R0,R1} MOV R0,#FR_FlashBase 01 LDR R1,[R0] ; Read the status register TST R1,#&0080 ; Check even SR.7 TSTNE R1,#&8000 ; Check odd SR.7 BEQ %BT01 ; Repeat until both set TST R1,#&0020 ; Check even SR.5 TSTEQ R1,#&2000 ; Check odd SR.5 BNE FR_ceEraseError LDMFD R13!,{R0,R1} MOV PC,LR FR_ceEraseError MOV R1,#&50 ORR R1,R1,R1,LSL #8 STR R1,[R0] ; Write Clear Status Register command (&50) to beth devices BL FR_ResetToReadArray BL FR_MakeROM0ReadOnly LDMFD R13!,{R0,R1} MOV R0,#FR_EraseErrorState-FR_BorderStateTable B FR_Error FR_DoWriteBlock ROUT ;Writes a block (256KB) of data to flash memory ;On entry ; r0=Block Address (real memory address) ; r1=Pointer to data to write ;On exit ; r0,r1 have advanced by the block size (256KB) STMFD R13!,{R2,R3,LR} MOV R2,R1 MOV R1,R0 MOV R3,#FR_BlockSize 01 BL FR_DoWriteBuffer SUBS R3,R3,#FR_BufferSize BNE %BT01 MOV R0,R1 MOV R1,R2 LDMFD R13!,{R2,R3,PC} FR_DoWriteBuffer ROUT ;Write a buffer full of data (64 bytes) to flash memory ;On entry ; r0=Block Address ; r1=Start Address ; r2=Pointer to data to write ;On exit ; r0 preserved ; r1,r2 have increased by 64 bytes STMFD R13!,{R3,R4,LR} MOV R3,#&E8 ORR R3,R3,R3,LSL #8 01 STR R3,[R0] ; Write the Write to Buffer command (&E8) to both devices LDR R4,[R0] ; Read the XSR TST R4,#&0080 ; Check even XSR.7 TSTNE R4,#&8000 ; Check odd XSR.7 BEQ %BT01 ; Repeat until both set MOV R3,#(FR_DeviceBufferSize:SHR:1)-1 ; No. of (16-bit) words to write - 1 ORR R3,R3,R3,LSL #8 STR R3,[R0] ; Write the (16-bit) word count to both devices MOV R3,#FR_BufferSize 02 LDR R4,[R2],#4 STR R4,[R1],#4 ; Write a (16-bit) word of data to each device SUBS R3,R3,#4 BNE %BT02 MOV R3,#&D0 ORR R3,R3,R3,LSL #8 STR R3,[R0] ; Write the Confirm command (&D0) to both devices 03 LDR R4,[R0] ; Read the status register TST R4,#&0080 ; Check even SR.7 TSTNE R4,#&8000 ; Check odd SR.7 BEQ %BT03 ; Repeat until both set TST R4,#&0008 ; Check even SR.3 TSTEQ R4,#&0800 ; Check odd SR.3 BNE FR_dwbfVoltageRangeError TST R4,#&0002 ; Check even SR.1 TSTEQ R4,#&0200 ; Check odd SR.1 BNE FR_dwbfDeviceProtectError TST R4,#&0010 ; Check even SR.4 TSTEQ R4,#&1000 ; Check odd SR.4 BNE FR_dwbfProgramError ; Programming completed successfully LDMFD R13!,{R3,R4,PC} FR_dwbfVoltageRangeError MOV R0,#FR_VoltageRangeErrorState-FR_BorderStateTable B FR_dwbfErrorExit FR_dwbfDeviceProtectError MOV R0,#FR_DeviceProtectErrorState-FR_BorderStateTable B FR_dwbfErrorExit FR_dwbfProgramError MOV R0,#FR_ProgramErrorState-FR_BorderStateTable FR_dwbfErrorExit MOV R3,#&50 ORR R3,R3,R3,LSL #8 MOV R4,#FR_FlashBase STR R1,[R4] ; Write Clear Status Register command (&50) to beth devices BL FR_ResetToReadArray BL FR_MakeROM0ReadOnly LDMFD R13!,{R3,R4,LR} B FR_Error FR_VerifyBlock ROUT ;Compare a block (256KB) of data to flash memory ;On entry ; r0=Block Address (real memory address) ; r1=Pointer to block to compare ;On exit ; r0,r1 have advanced by the block size (256KB) STMFD R13!,{R2-R4} MOV R2,#FR_BlockSize 01 LDR R3,[R0],#4 LDR R4,[R1],#4 CMP R3,R4 BNE FR_VerifyError SUBS R2,R2,#4 BNE %BT01 LDMFD R13!,{R2-R4} MOV PC,LR FR_VerifyError MOV R0,#FR_VerifyErrorState-FR_BorderStateTable B FR_Error FR_StackBaseVal & FR_StackBase FR_TransferBuffVal & FR_TransferBuffAddr FR_RAMCodeEnd END