电表在不同供电模式下的安全过渡
; Switch to M6520 when chip is available.
; Standard SFR Symbols
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
DPL DATA 82H
DPH DATA 83H
USER1 DATA 90H
DIR1 DATA 91H
FCTRL DATA 0B2H
IPH DATA 0B9H
IPL DATA 0A9H
IRCON DATA 0C0H
IEN0 DATA 0A8H
IEN1 DATA 0B8H
NAME ?C_STARTUP
?C_C51STARTUP SEGMENT CODE
?STACK SEGMENT IDATA
RSEG ?STACK
DS 1
EXTRN CODE (?C_START)
PUBLIC ?C_STARTUP
PUBLIC _?TRIM_TEST
CSEG AT 0
?C_STARTUP: LJMP STARTUP1
RSEG ?C_C51STARTUP
STARTUP1:
CLR IEN0^7 ; Disable interrupts
; To enable secure mode, remove the semicolon of the next line
; ORL FCTRL,#40H ; set secure bit
MOV 0E8h,#0FFh ; Refresh nonmaskable watchdog.
; Set system interrupt priorities; more frequent are higher priority.
MOV IPH,#01DH ; From code in options_gbl.h, main.c
MOV IPL,#00AH ; From code in options_gbl.h
; Clear PLL_OK interrupt (bit3), and others
MOV IRCON,#0
; Enable PLL_OK interrupt
MOV DPTR,#2007H ; Set EX_PLL
MOV A,#20H
MOVX @DPTR,A
; Enable interrupts
MOV IEN1,#08H ; Enable INT4, the PLL_OK interrupt
MOV IEN0,#80H ; Enable all interrupts
ACALL _?TRIM_TEST ; Test 6521's trims
IF IDATALEN > 0
MOV R0,#IDATALEN - 1
CLR A
IDATALOOP: MOV @R0,A
DJNZ R0,IDATALOOP
ENDIF
IF XDATALEN > 0
MOV DPTR,#XDATASTART
MOV R7,#LOW (XDATALEN)
IF (LOW (XDATALEN)) > 0
MOV R6,#(HIGH (XDATALEN)) +1
ELSE
MOV R6,#HIGH (XDATALEN)
ENDIF
CLR A
XDATALOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATALOOP
DJNZ R6,XDATALOOP
ENDIF
IF PPAGEENABLE > 0
MOV PPAGE_SFR,#PPAGE
ENDIF
IF PDATALEN > 0
MOV R0,#LOW (PDATASTART)
MOV R7,#LOW (PDATALEN)
CLR A
PDATALOOP: MOVX @R0,A
INC R0
DJNZ R7,PDATALOOP
ENDIF
IF IBPSTACK > 0
EXTRN DATA (?C_IBP)
MOV ?C_IBP,#LOW IBPSTACKTOP
ENDIF
IF XBPSTACK > 0
EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
IF PBPSTACK > 0
EXTRN DATA (?C_PBP)
MOV ?C_PBP,#LOW PBPSTACKTOP
ENDIF
MOV SP,#?STACK-1
LJMP ?C_START
; Read a trim whose index is in A. Return the trim in A.
CSEG AT 100H
FUSE_TABLE:
DB 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
; Trim test. Prefix _? tells Keil C it's reentrant.
_?TRIM_TEST:
PUSH IEN0
PUSH PSW ; Save registers, so it's reentrant.
MOV PSW,00H ; Select registers before saving them
PUSH DPL
PUSH DPH
PUSH ACC
MOV A,R7 ; Save R7 from the current register set.
PUSH ACC
MOV A,R6 ; Save R6 from the current register set.
PUSH ACC
CLR IEN0.7
; Wait for all fuses to be read once before checking fuses
; Complete fuse read takes 45 xtal clock cycles (1 fuse per xtal clock)
MOV R7,#21 ; Wait 21x4 = 48 cycles
loop_inner: DJNZ R7,loop_inner ; 4 cycles (in brownout, 1 cycle/clk)
mov DPH, #HIGH(FUSE_TABLE)
fuse_test_frst: ; check if values previously stored
mov DPL,#LOW(FUSE_TABLE)
clr a
movc a,@a+dptr ; read fuse table
xrl a,#55H
jnz fuse_save
MOV DPTR,#2003H ; Check if in brownout mode
MOVX A,@DPTR
JB ACC.6,PASS ; Mission mode, so don't check.
fuse_test:
mov r7,#8 ; byte counter
fuse_test_lp1:
mov DPTR,#FUSE_TABLE ; load pointer to fuse table
mov a,r7
movc a,@a+dptr ; read fuse table
mov r6,a
mov a,r7
MOV DPTR,#20FDH ; TRIMSEL address
MOVX @DPTR,A ; load reg to read trim
MOV DPL,#0FFH ; TRIM value address
MOVX A,@DPTR ; Get trim value
cjne a,06H,FAIL ; test if flash read and trim ==
djnz r7,fuse_test_lp1
JMP PASS
fuse_save:
MOV DPTR,#2003H ; Check if in brownout mode
MOVX A,@DPTR
; If brownout mode, don't save them and enter sleep.
JNB ACC.6,FAIL
; mov 84H,#LOW(FUSE_TABLE)
mov r7,#8 ; byte counter
fuse_save_lp1:
mov a,r7
MOV DPTR,#20FDH ; TRIMSEL address
MOVX @DPTR,A ; load reg to read trim
MOV DPL,#0FFH ; TRIM value address
MOVX A,@DPTR ; Get trim value
mov r6,a
mov a,r7
mov dptr,#FUSE_TABLE
add a,DPL
mov DPL,a
mov a,r6
orl 0B2H,#01H ; set to flash write
movx @dptr,a ; write fuse table byte
djnz r7,fuse_save_lp1
mov a,#55H ; contr
- 汽车上路预防性安全设计浅析(12-09)
- 安全电压对供电电源的要求(12-08)
- [原创]硬件安全IC以低成本实现高回报(02-09)
- 网络安全IDS:无线网络电磁干扰屏蔽技术及应用(01-12)
- 自行车发电及安全预警系统设计(01-24)
- 通信机房安全隐患整改UPS应用方案介绍(09-17)