Что-то я уже обалдеваю от загрузчика :-/ После выдачи команды на запись страницы флэш происходит зависание до передёргивания питания. Символ, который передаётся после "LAST ALIVE POINT" приходит, а после - молчание. Где-то я туплю, но вот никак не пойму - где. Сначала думал, что нужно из ОЗУ выполняться, чтобы флэш писать, а нифига, не помогло. Посмотрите, пожалуйста, буду рад любым соображениям.
CODE
;
; main.s
;
; external OSC 16 MHz
; master clock at 28.0 MHz
INCLUDE common.inc
BOOTLOADER_AREA_SIZE EQU 0x400
APP_MAX_SIZE EQU (0x8000 - BOOTLOADER_AREA_SIZE)
APPLICATION_BEGIN_ADDR EQU 0x100400
APP_SIZE_OFFSET EQU 0x0
APP_CHECKSUM_OFFSET EQU 0x4
APP_EXCEPTIONS_START EQU 0x8
FLASH_START_ADDR EQU 0x100000
RAM_START_ADDR EQU 0x200000
DBGU_TXRDY_WAIT EQU 0x60000
DBGU_RXRDY_WAIT EQU 0x500000
AREA RESET, CODE, READONLY
ARM
; exception vectors
exception_block_start
ldr pc, Reset_Addr
ldr pc, Undef_Addr
ldr pc, SWI_Addr
ldr pc, PAbt_Addr
ldr pc, DAbt_Addr
nop
ldr pc, [pc, #-0xF20] ; go to by IRQ vector
ldr pc, FIQ_Addr
exception_vectors
; address map for exeption vectors
Reset_Addr
DCD Reset_Handler
Undef_Addr
DCD Undef_Handler
SWI_Addr
DCD SWI_Handler
PAbt_Addr
DCD PAbt_Handler
DAbt_Addr
DCD DAbt_Handler
FIQ_Addr
DCD FIQ_Handler
exception_block_end
; loopbacks for unused exception vectors
Undef_Handler
SWI_Handler
PAbt_Handler
DAbt_Handler
FIQ_Handler
unusedExceptionLoopback
b unusedExceptionLoopback
AREA TEXT, CODE, READONLY
ARM
; reset handler
EXPORT Reset_Handler
ENTRY
Reset_Handler
; reset controller
ldr r0, =RSTC_BASE
ldr r1, =0xA5000401 ; KEY = 0xA5, BODIEN = 0, ERSTL = 4, URSTIEN = 0, URSTEN = 1
str r1, [r0, #RSTC_MR]
; flash controller: 0 wait states, MCK = 28 MHz
ldr r0, =EFC_BASE
ldr r1, =0x002A0000 ; FMCN = 0x2B, FWS = 0, NEBP = 0, PROGE = 0, LOCKE = 0, FRDY = 0
str r1, [r0, #EFC0_FMR]
; watchdog
ldr r0, =WDT_BASE
ldr r1, =0x00008000 ; disable watchdog
str r1, [r0, #WDT_MR]
; copy self to RAM
ldr r0, =0x100000
ldr r1, =0x200000
ldr r3, =256
selfCopyLoop
ldr r4, [r0], #4
str r4, [r1], #4
subs r3, r3, #1
bne selfCopyLoop
; execute remap
ldr r0, =EFC_BASE
ldr r1, =1
str r1, [r0, #MC_RCR]
ldr PC, =(0x200000 + continueEntry - 0x100000)
continueEntry
; enable main oscillator and PLL
ldr r0, =PMC_BASE
; after that we have master clock at 32768 Hz
ldr r1, =0x00000701 ; OSCOUNT = 7, OSCBYPASS = 0, MOSCEN = 1
str r1, [r0, #PMC_MOR]
; wait for stabilization
init_waitMainOsc
ldr r1, [r0, #PMC_SR]
tst r1, #PMC_B_MOSCS
beq init_waitMainOsc
; pll (16000000 / 1) * 7 = 112000000
ldr r1, =0x00063F01 ; USBDIV = 0, MUL = 0x06, OUT = 0, PLLCOUNT = 0x4F, DIV = 0x01
str r1, [r0, #PMC_PLLR]
; wait for lock
init_waitPll
ldr r1, [r0, #PMC_SR]
tst r1, #PMC_B_LOCK
beq init_waitPll
; setup prescaler
ldr r1, =0x00000008 ; MDIV = 0, PRES = 2, CSS = 0
str r1, [r0, #PMC_MCKR]
; wait for master clock
init_waitPrescaler
ldr r1, [r0, #PMC_SR]
tst r1, #PMC_B_MCKRDY
beq init_waitPrescaler
; setup master clock source
ldr r1, =0x0000000B ; MDIV = 0, PRES = 2, CSS = 3
str r1, [r0, #PMC_MCKR]
; wait for master clock
init_waitMasterClock
ldr r1, [r0, #PMC_SR]
tst r1, #PMC_B_MCKRDY
beq init_waitMasterClock
; after that we have master clock at 28 MHz
; setup stack for IRQ mode
msr CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
ldr sp, =0x202000
; setup stack for user mode
msr CPSR_c, #Mode_USR:OR:F_Bit
ldr sp, =0x201F00
; now cpu in user mode, FIQ disabled
; enable clock for PIOA controller
ldr r1, =( 1 << 2 )
str r1, [r0, #PMC_PCER]
; setup IO pins roles and states
ldr r0, =PIO_BASE
; set all lines as IO, except PA9 & PA10
ldr r1, =0xFFFFF9FF
str r1, [r0, #PIO_PER]
; set lines as inputs
str r1, [r0, #PIO_ODR]
; get buttons 3 and 4
ldr r2, [r0, #PIO_PDSR]
; set PA9 & PA10 under DBGU control
mvn r1, r1
str r1, [r0, #PIO_PDR]
str r1, [r0, #PIO_ASR]
; set up DBGU
ldr r0, =DBGU_BASE
ldr r1, =0x800 ; PAR = no parity
str r1, [r0, #DBGU_MR]
ldr r1, =91 ; 19200 baud
str r1, [r0, #DBGU_BRGR]
ldr r1, =0x50 ;TXEN | RXEN
str r1, [r0, #DBGU_CR]
; check PA19 and PA20, if it zero - go to init loader
tst r2, #0x180000
beq init_loader
; verify application checksum
; address of first byte of application
ldr r2, =APPLICATION_BEGIN_ADDR
; load application size
ldr r3, [r2], #4
ldr r4, =127 ; min size - 1
; if app size < threshold, go to init loader
cmp r3, r4
bls init_loader
ldr r4, =APP_MAX_SIZE
; if app size > limit, go to init loader
cmp r3, r4
bhi init_loader
; load application checksum
ldr r4, [r2], #4
; calculate checksum
ldr r5, =0
checksum_loop
ldr r6, [r2], #4
eor r6, r5, lsl #1
orr r6, r5, lsr #31
mov r5, r6
subs r3, #4
bhi checksum_loop
; compare checksums
cmp r4, r5
bne init_loader
starting_app
; starting application
; copy exception table to RAM
ldr r0, =(APPLICATION_BEGIN_ADDR + APP_EXCEPTIONS_START)
ldr r1, =(0x200000 + exception_vectors - 0x100000)
ldmia r0, {r2-r7}
stmia r1, {r2-r7}
; jump to reset vector
ldr PC, =0
init_loader
; waiting for command
loaderWaitCmd
ldr r2, =DBGU_BASE
bl dbguReadOneByte
tst r5, r5
beq loaderWaitCmd
mov LR, PC
sub LR, LR, #24
subs r1, r1, #1 ; if r1 == 1
beq loaderSendHello ; send hello string
subs r1, r1, #1 ; if r1 == 2
beq loaderReadFirmware ; receive firmware and store it to flash
b loaderWaitCmd
; send hello string to remote
loaderSendHello
ldr r0, =strHello
b dbguSendBytes
; receive firmware from remote and store it to flash
loaderReadFirmware
str LR, [SP, #-4]!
; start addr for write
ldr r12, =APPLICATION_BEGIN_ADDR
; first send ACK
bl sendAck
; receive size (4 bytes) of firmware, size = count of 128-bytes pages
ldr r0, =fwSize
ldr r3, =4
bl dbguReadBytes
tst r3, r3
bne loaderReadFirmware_crash
; load received value
ldr r10, [r0]
; check size
tst r10, r10
beq loaderReadFirmware_crash
ldr r3, =(APP_MAX_SIZE / 128)
cmp r10, r3
bhi loaderReadFirmware_crash
; send ACK
bl sendAck
; init destination address
ldr r9, =(BOOTLOADER_AREA_SIZE / 128)
; receive 128 bytes from remote
loaderReadFirmware_loop
ldr r3, =128
bl dbguReadBytes
tst r3, r3
bne loaderReadFirmware_crash
; write data to flash page buffer
ldr r0, =flashSectorBuf
ldr r1, =128
pageBufCopy
ldr r3, [r0], #4
str r3, [r12], #4
subs r1, r1, #4
bhi pageBufCopy
; send ACK 1
bl sendAck
; EFC base addr
ldr r0, =EFC_BASE
; wait for FRDY
ldr r3, =6144
writePageWait
ldr r4, [r0, #EFC0_FSR]
tst r4, #1
bne writePageWriteCmd
subs r3, r3, #1
bne writePageWait
b loaderReadFirmware_crash
writePageWriteCmd
; send ACK 2 [[[[[[[[[[ LAST ALIVE POINT ]]]]]]]]]]
bl sendAck
; write sector to flash
ldr r0, =EFC_BASE
ldr r1, =0x5A000001
orr r1, r9, lsl #8
str r1, [r0, #EFC0_FCR]
; send ACK 3 [[[[[[[[[[ THIS ACK NOT RECEIVED ]]]]]]]]]]
bl sendAck
; wait for FRDY
ldr r0, =EFC_BASE
ldr r3, =6144
writePageWait2
ldr r4, [r0, #EFC0_FSR]
tst r4, #1
bne writePageCheckErrors
subs r3, r3, #1
bne writePageWait2
b loaderReadFirmware_crash
writePageCheckErrors
; send ACK 4
bl sendAck
; check for errors
tst r4, #0xA ; PROGE | LOCKE
bne loaderReadFirmware_crash
; send ACK 5
bl sendAck
; inc page
add r9, r9, #1
; dec pages count
subs r10, r10, #1
bhi loaderReadFirmware_loop
; send success message
ldr r0, =strAllOk
bl dbguSendBytes
; wait another cmd
ldr PC, [SP], #4
loaderReadFirmware_crash
; send NACK
ldr r0, =strErr
bl dbguSendBytes
ldr r0, =0x100000
sendNackWaitLoop
subs r0, r0, #1
bne sendNackWaitLoop
; something wrong, reset chip
ldr r0, =RSTC_BASE
ldr r1, =0xA500000D ; EXTRST | PERRST | PROCRST
str r1, [r0, #RSTC_CR]
loaderReadFirmare_crash_loop
b loaderReadFirmare_crash_loop
sendAck
stmfd SP!, {r0,r1,LR}
ldr r0, =strAck
bl dbguSendBytes
ldmfd SP!, {r0,r1,PC}
; write one byte to DBGU transmitter holding register
; IN
; r1 - byte to send
; OUT
; r3 != 0 if no error
dbguSendOneByte
; load counter
ldr r3, =DBGU_TXRDY_WAIT
; first wait for TXRDY
dbguSendOneByte_wait
ldr r4, [r2, #DBGU_SR]
tst r4, #2 ; TXRDY
bne dbguSendOneByte_send
subs r3, r3, #1
bne dbguSendOneByte_wait
bx LR
dbguSendOneByte_send
str r1, [r2, #DBGU_THR]
mov PC, LR
; read one byte from DBGU receiver holding register
; OUT
; r1 - received byte
; r5 != 0 if no error
dbguReadOneByte
; load counter
ldr r5, =DBGU_RXRDY_WAIT
; wait for RXRDY
dbguReadOneByte_wait
ldr r4, [r2, #DBGU_SR]
tst r4, #1 ; RXRDY
bne dbguReadOneByte_read
subs r5, r5, #1
bne dbguReadOneByte_wait
bx LR
dbguReadOneByte_read
ldr r1, [r2, #DBGU_RHR]
mov PC, LR
; send some bytes by DBGU
; IN
; r0 - start address of ASCIIZ string
; OUT
; r1 == 0 if no error
dbguSendBytes
stmfd SP!, {r0,r2-r4,LR}
ldr r2, =DBGU_BASE
dbguSendBytes_loop
ldrb r1, [r0], #1
tst r1, r1
beq dbguSendBytes_exit
bl dbguSendOneByte
tst r3, r3
bne dbguSendBytes_loop
dbguSendBytes_exit
ldmfd SP!, {r0,r2-r4,PC}
; read some bytes by DBGU
; IN
; r0 - start address of target buffer
; r3 - count of bytes to read
; OUT
; r3 == 0 if no error
dbguReadBytes
stmfd SP!, {r0-r2,r4,r5,LR}
ldr r2, =DBGU_BASE
dbguReadBytes_loop
bl dbguReadOneByte
tst r5, r5
beq dbguReadBytes_exit
strb r1, [r0], #1
subs r3, r3, #1
bne dbguReadBytes_loop
dbguReadBytes_exit
ldmfd SP!, {r0-r2,r4,r5,PC}
strHello
DCB "sBoot v0.1", 13, 10, 0
strAck
DCB ">", 0
strErr
DCB "E", 0
strAllOk
DCB "Ok", 13, 10, 0
AREA STACK, NOINIT, READWRITE
SPACE 0x400
fwSize
SPACE 4
flashSectorBuf
SPACE 128
END