AVR Assembler Source Blog

Ремонт частотных преобразователей AVR Assembler Source Blog: CRC_check_program_memory_AVR236_appnote

Wednesday, October 9, 2013

CRC_check_program_memory_AVR236_appnote

проверка частотных преобразователей
                              ;**** A P P L I C A T I O N   N O T E   A V R 236 ************************
                              ;*
                              ;* Title:  CRC check of program memory
                              ;* Version:  1.0
                              ;* Last updated: 98.06.15
                              ;* Target:  AT90Sxxxx (All AVR Devices with LPM instr, not AT90S1200)
                              ;*
                              ;* Support E-mail: avr@atmel.com
                              ;*
                              ;* NOTE: Always check out Atmels web site, www.atmel.com for the latest and updated 
                              ;* version of the software.
                              ;*
                              ;* DESCRIPTION
                              ;* This application note describes how to perform CRC computation 
                              ;* of code memory contents using a simple algoritm. 
                              ;* To generate CRC checksum load the register "status" with 00 and call the routine 
                              ;* "crc_gen". The resulting checksum is placed in the registers
                              ;* byte2(low byte) and byte3(high byte).
                              ;*
                              ;* To check the CRC checksum load the register "status" with FF and call the routine 
                              ;* "crc_gen". The resulting checksum is placed in the registers
                              ;* byte2(low byte) and byte3(high byte). If the checksum is 00 the program code is
                              ;* correct, if the checksum is non-zero an error has been introduced in the program code
                              ;**************************************************************************


.include "..\8515def.inc"
.device AT90S8515

                              ;***** Constants

.equ PROGSIZE=0x1FFF          ; Size of program memory(bytes)
.equ CR=0x8005                ; CRC divisor value

                              ;**************************************************************************
                              ;*
                              ;*      PROGRAM START - EXECUTION STARTS HERE
                              ;*
                              ;**************************************************************************

.cseg

.org $0000
 rjmp RESET                   ;Reset handle


                              ;***************************************************************************
                              ;*
                              ;* "crc_gen" - Generation and checking of CRC checksum
                              ;*
                              ;* This subroutine generates the checksum for the program code.
                              ;* 32 bits are loaded into 4 register, the upper 16 bits are XORed
                              ;* with the divisor value each time a 1 is shifted into the carry flag 
                              ;* from the MSB.
                              ;*
                              ;* If the status byte is 0x00,the routine will generate new checksum:
                              ;* After the computing the code 16 zeros are
                              ;* appended to the code and the checksum is calculated. 
                              ;* 
                              ;* If the status byte is different from 0X00, the routine will check if the current checksum is valid.
                              ;* After the computing the code the original checksum are
                              ;* appended to the code and calculated. The result is zero if no errors occurs
                              ;* The result is placed in registers byte2 and byte3
                              ;*  
                              ;* Number of words :44 + return
                              ;* Number of cycles :program memory size(word) * 175(depending on memory contens)
                              ;* Low registers used :6 (byte0,byte1,byte2,byte3)
                              ;* High registers used  :7 (sizel,sizeh,crdivl,crdivh,count,status,zl,zh) 
                              ;*
                              ;***************************************************************************

                              ;***** Subroutine Register Variables

.def byte0=r0                 ; Lower byte of lower word
.def byte1=r1                 ; Upper byte of lower word
.def byte2=r2                 ; Lower byte of upper word
.def byte3=r3                 ; Upper byte of upper word
.def crc=r4                   ; CRC checksum low byte
.def crch=r5                  ; CRC checksum high byte
.def sizel=r17                ; Program code size register
.def sizeh=r18
.def crdivl=r19               ; CRC divisor register
.def crdivh=r20
.def count=r21                ; Bit counter 
.def status=r22               ; Status byte: generate(0) or check(1)

crc_gen:
       ldi sizel,low(PROGSIZE);Load end of program memory address
       ldi sizeh,high(PROGSIZE) 
       clr zl                 ;Clear Z pointer
       clr zh    
       ldi crdivh,high(CR)    ;Load divisor value
       ldi crdivl,low(CR)
       lpm                    ;Load first memory location
       mov byte3,byte0        ;Move to highest byte
       adiw zl,0x01           ;Increment Z pointer
       lpm                    ;Load second memory location
       mov byte2,byte0  

new_word:
       cp zl,sizel            ;Loop starts here
       cpc zh,sizeh           ;Check for end of code
       brge end               ;Jump if end of code
       adiw zl,0x01   
       lpm                    ;Load high byte
       mov byte1,byte0        ;Move to upper byte
       adiw zl,0x01           ;Increment Z pointer
       lpm                    ;Load program memory location
       rcall rot_word         ;Call the rotate routine
       rjmp new_word

end:                       
                              ;ret ;uncomment this line if checksum is stored in last flash memory address.
       ldi count,0x11  
       cpi status,0x00  
       brne check
       clr byte0              ;Append 16 bits(0x0000) to
       clr byte1              ;the end of the code for CRC generation
       rjmp gen 
check: 
       mov byte0,crc          ;Append the original checksum to
       mov byte1,crch         ;the end of the code for CRC checking
gen: 
       rcall rot_word         ;Call the rotate routine
       mov crc,byte2  
       mov crch,byte3
       ret                    ;Return to main prog
 
rot_word:
       ldi count,0x11
rot_loop:
       dec count              ;Decrement bit counter
       breq stop              ;Break if bit counter = 0
       lsl byte0              ;Shift zero into lowest bit
       rol byte1              ;Shift in carry from previous byte
       rol byte2              ;Preceede shift
       rol byte3   
       brcc rot_loop          ;Loop if MSB = 0   
       eor byte2,crdivl
       eor byte3,crdivh       ;XOR high word if MSB = 1
       rjmp rot_loop
stop: 
       ret

                              ;***************************************************************************
                              ;* 
                              ;* EERead_seq
                              ;*
                              ;* This routine reads the 
                              ;* EEPROM into the global register variable "temp".
                              ;*
                              ;* Number of words :4+ return
                              ;* Number of cycles :8 + return 
                              ;* High Registers used :4 (temp,eeadr,eeadrh,eedata)
                              ;*
                              ;***************************************************************************

.def temp=r16 
.def eeadr=r23
.def eeadrh=r24
.def eedata=r25

                              ;***** Code

eeread:
       out EEARH,eeadrh       ;output address high byte
       out EEARL,eeadr        ;output address low byte
       sbi EECR,EERE          ;set EEPROM Read strobe
       in eedata,EEDR         ;get data
       ret

                              ;***************************************************************************
                              ;* 
                              ;* EEWrite
                              ;*
                              ;* This subroutine waits until the EEPROM is ready to be programmed, then
                              ;* programs the EEPROM with register variable "EEdwr" at address "EEawr"
                              ;*
                              ;* Number of words :7 + return
                              ;* Number of cycles :13 + return (if EEPROM is ready)
                              ;* Low Registers used :None
                              ;* High Registers used: ;4 (temp,eeadr,eeadr,eedata)
                              ;*
                              ;***************************************************************************

.def temp=r16 
.def eeadr=r23
.def eeadrh=r24
.def eedata=r25

eewrite:
       sbic EECR,EEWE         ;If EEWE not clear
       rjmp EEWrite           ;Wait more
       out EEARH,eeadrh       ;Output address high byte
       out EEARL,eeadr        ;Output address low byte
       out EEDR,eedata        ;Output data
       sbi EECR,EEMWE
       sbi EECR,EEWE          ;Set EEPROM Write strobe
       ret


                              ;************************************************************************
                              ;*
                              ;*  Start Of Main Program
                              ;*
.cseg
.def crc=r4                   ;Low byte of checksum to be returned
.def crch=r5                  ;High byte of checksum to be returned
.def temp=r16  
.def status=r22               ;Status byte: generate(0) or check(1)
.def eeadr=r23
.def eeadrh=r24
.def eedata=r25

RESET: 
       ldi r16,high(RAMEND)   ;Initialize stack pointer 
       out SPH,r16            ;High byte only required if 
       ldi r16,low(RAMEND)    ;RAM is bigger than 256 Bytes
       out SPL,r16

       ldi temp,0xff 
       out DDRB,temp          ;Set PORTB as output
       out PORTB,temp         ;Write 0xFF to PORTB
       clr status             ;Clear status register, prepare for CRC generation
       rcall crc_gen
 
       ldi eeadr,0x01         ;Set address low byte for EEPROM write
       ldi eeadrh,0x00        ;Set address high byte for EEPROM write
       mov eedata,crc         ;Set CRC low byte in EEPROM data
       rcall eewrite          ;Write EEPROM

       ldi eeadr,0x02         ;Set address low byte for EEPROM write
       ldi eeadrh,0x00        ;Set address high byte for EEPROM write
       mov eedata,crch        ;Set CRC high byte in EEPROM data
       rcall eewrite          ;Write EEPROM

       out PORTB,crc          ;Output CRC low value to PORTB
 
mainloop:
       sbic EECR,EEWE         ;If EEWE not clear
       rjmp mainloop          ;Wait more

                              ;********** Insert program code here *************

       ldi eeadr,0x01         ;Set address low byte for EEPROM read
       ldi eeadrh,0x00        ;Set address high byte for EEPROM read
       rcall eeread           ;Read EEPROM
       mov crc,eedata         ;Read CRC low byte from EEPROM

       ldi eeadr,0x02         ;Set address low byte for EEPROM read
       ldi eeadrh,0x00        ;Set address high byte for EEPROM read
       rcall eeread           ;Read EEPROM
       mov crch,eedata        ;Read CRC low byte from EEPROM

       ser status             ;Set status register, prepare for CRC checking
       rcall crc_gen

loop: 
       out PORTB,crc          ;Output CRC low value to PORTB
       rjmp loop

.exit

No comments:

Post a Comment