.NOLIST
.INCLUDE "m128def.inc"
.INCLUDE "_macros.asm"
.MACRO SDCS_SET
SBI PORTB,0
.ENDMACRO
.MACRO SDCS_CLR
CBI PORTB,0
.ENDMACRO
.MACRO LED_ON
CBI PORTB,7
.ENDMACRO
.MACRO LED_OFF
SBI PORTB,7
.ENDMACRO
.LIST
.LISTMAC
.DEF POLY_LO =R06 ;всегда = $21
.DEF POLY_HI =R07 ;всегда = $10
.DEF FF_FL =R08
.DEF CRC_LO =R09
.DEF CRC_HI =R10
.DEF ADR1 =R11
.DEF ADR2 =R12
.DEF FF =R13 ;всегда = $FF
.DEF ONE =R14 ;всегда = $01
.DEF NULL =R15 ;всегда = $00
.DEF DATA =R16
.DEF TEMP =R17
.DEF COUNT =R18
.DEF BITS =R19
.DEF GUARD =R22
;локально используются: R0,R1,R20,R21,R24,R25
.EQU DBSIZE_HI =HIGH(4096)
.EQU DBMASK_HI =HIGH(4095)
.EQU nCONFIG =PORTF0
.EQU nSTATUS =PORTF1
.EQU CONF_DONE =PORTF2
.EQU SOH =$01
.EQU EOT =$04
.EQU ACK =$06
.EQU NAK =$15
.EQU CAN =$18
.EQU CMD_17 =$51 ;read_single_block
.EQU ACMD_41 =$69 ;sd_send_op_cond
.EQU ANSI_RED =$31
.EQU ANSI_GREEN =$32
.EQU ANSI_YELLOW =$33
.EQU ANSI_WHITE =$37
.EQU FLASHSIZE=480 ;размер обновляемой области FLASH в блоках по 256 байт
.EQU MAIN_VERS=$EFF8 ;указатель на описатель версии осн.прошивки
;
;--------------------------------------
;
.DSEG
.ORG $0100
BUFFER: ;главный буфер
.ORG $0200
BUFSECT: ;буфер сектора
.ORG $0400
BUF4FAT: ;временный буфер (FAT и т.п.)
.ORG $0600
HEADER: ;заголовок файла
.ORG $0680
CAL_FAT:.BYTE 1 ;тип обнаруженной FAT
MANYFAT:.BYTE 1 ;количество FAT-таблиц
BYTSSEC:.BYTE 1 ;количество секторов в кластере
ROOTCLS:.BYTE 4 ;сектор начала root директории
SEC_FAT:.BYTE 4 ;количество секторов одной FAT
RSVDSEC:.BYTE 2 ;размер резервной области
STARTRZ:.BYTE 4 ;начало диска/раздела
FRSTDAT:.BYTE 4 ;адрес первого сектора данных от BPB
SEC_DSC:.BYTE 4 ;количество секторов на диске/разделе
CLS_DSC:.BYTE 4 ;количество кластеров на диске/разделе
FATSTR0:.BYTE 4 ;начало первой FAT таблицы
FATSTR1:.BYTE 4 ;начало второй FAT таблицы
TEK_DIR:.BYTE 4 ;кластер текущей директории
KCLSDIR:.BYTE 1 ;кол-во кластеров директории
NUMSECK:.BYTE 1 ;счетчик секторов в кластере
TFILCLS:.BYTE 4 ;текущий кластер
MPHWOST:.BYTE 1 ;кол-во секторов в последнем кластере
KOL_CLS:.BYTE 4 ;кол-во кластеров файла минус 1
SDHC: .BYTE 1
STEP:
SDERROR:.BYTE 1
LASTSECFLAG:
.BYTE 1
;
;--------------------------------------
;
.CSEG
.ORG $F000
BOOTLOADER_BEGIN:
RESET: CLI
;Причина реcета? Если Watchdog то на основную программу
IN DATA,MCUCSR
ANDI DATA,0B00001000
BREQ START1
JMP 0
;
BAD_BOOTLDR_CRC:
START1: CLR NULL
LDI GUARD,$5A
LDI TEMP,$01
MOV ONE,TEMP
LDI TEMP,$FF
MOV FF,TEMP
LDI TEMP,$21
MOV POLY_LO,TEMP
LDI TEMP,$10
MOV POLY_HI,TEMP
;WatchDog OFF, если вдруг включен
LDI TEMP,0B00011111
OUT WDTCR,TEMP
OUT WDTCR,NULL
;
LED_ON
SBI DDRB,7
;стек
LDI TEMP,LOW(RAMEND)
OUT SPL,TEMP
LDI TEMP,HIGH(RAMEND)
OUT SPH,TEMP
;проверка CRC загрузчика
LDIZ BOOTLOADER_BEGIN*2 ;адрес в байтах
OUT RAMPZ,ONE
LDIY BOOTLOADER_END-BOOTLOADER_BEGIN ;длина в словах
RCALL CALK_CRC_FLASH
BRNE BAD_BOOTLDR_CRC ;что делать, если не правильная crc у bootloaderа ? я делаю перезапуск.
;хочет ли пользователь обновиться ?
SBIS PINC,7 ;нажат "SoftReset" ?
RJMP UPDATE_ME
;проверка CRC осн.программы
START8: RCALL CRCMAIN
BRNE UPDATE_ME ;если некорректная CRC
;
;запуск watchdog-а (по срабатыванию переход на осн.программу)
START9: CBI PORTE,6
LDI TEMP,0B00011000
OUT WDTCR,TEMP
GAVGAV: RJMP GAVGAV
;
;--------------------------------------
;проверка CRC осн.программы после обновления
CHECKIT:RCALL NEWLINE
LDIZ MSG_RECHECK*2
RCALL PRINTSTRZ
RCALL CRCMAIN
BRNE CHK_BAD
LDIZ MSG_MAINOK*2
RCALL PRINTSTRZ
RCALL NEWLINE2
LDIZ MSG_MAIN*2
RCALL PRINTSTRZ
LDIZ MAIN_VERS*2
RCALL PRINTVERS
RCALL NEWLINE2
RJMP START9
;
CHK_BAD:LDI DATA,ANSI_RED
RCALL ANSI_COLOR
LDIZ MSG_MAINBAD*2
RCALL PRINTSTRZ
RCALL DELAY_3SEC
;
;--------------------------------------
;
UPDATE_ME:
LDI TEMP, 0B01111001 ;
OUT PORTB,TEMP
LDI TEMP, 0B10000111 ; LED on, spi outs
OUT DDRB,TEMP
LDI TEMP, 0B00001000 ; ATX on
OUTPORT DDRF,TEMP
OUTPORT PORTF,TEMP
;SPI init
LDI TEMP,(1<<SPI2X)
OUT SPSR,TEMP
LDI TEMP,(1<<SPE)|(1<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)
OUT SPCR,TEMP
;UART1 Set baud rate
OUTPORT UBRR1H,NULL
LDI TEMP,5 ;115200 baud @ 11059.2 kHz, Normal speed
OUTPORT UBRR1L,TEMP
;UART1 Normal Speed
OUTPORT UCSR1A,NULL
;UART1 data8bit, 2stopbits
LDI TEMP,(1<<UCSZ1)|(1<<UCSZ0)|(1<<USBS)
OUTPORT UCSR1C,TEMP
;UART1 Разрешаем передачу
LDI TEMP,(1<<TXEN)
OUTPORT UCSR1B,TEMP
;вывод информации о версиях
LDIZ MSG_TITLE*2
RCALL PRINTSTRZ
LDIZ MSG_BOOT*2
RCALL PRINTSTRZ
LDIZ BOOT_VERS*2
RCALL PRINTVERS
RCALL NEWLINE
LDIZ MSG_MAIN*2
RCALL PRINTSTRZ
TST CRC_LO
BREQ UP01
LDIZ MSG_BADCRC*2
RCALL PRINTSTRZ
RJMP UP02
UP01: LDIZ MAIN_VERS*2
RCALL PRINTVERS
UP02: RCALL NEWLINE
;ждём включения ATX, а потом ещё чуть-чуть.
UP11: SBIS PINF,0 ;PINC,5 ; а если powergood нет вообще ?
RJMP UP11
LDI DATA,5
RCALL DELAY
LDIZ MSG_CFGFPGA*2
RCALL PRINTSTRZ
;загрузка FPGA
INPORT TEMP,DDRF
SBR TEMP,(1<<nCONFIG)
OUTPORT DDRF,TEMP
LDI TEMP,147 ;40 us @ 11.0592 MHz
LDFPGA1:DEC TEMP ;1
BRNE LDFPGA1 ;2
INPORT TEMP,DDRF
CBR TEMP,(1<<nCONFIG)
OUTPORT DDRF,TEMP
LDFPGA2:SBIS PINF,nSTATUS
RJMP LDFPGA2
LDIZ PACKED_FPGA*2
OUT RAMPZ,ONE
LDIY BUFFER
;(не трогаем стек! всё ОЗУ под буфер)
LDI TEMP,$80
MS: ELPM R0,Z+
ST Y+,R0
;-begin-PUT_BYTE_1---
OUT SPDR,R0
PUTB1: SBIS SPSR,SPIF
RJMP PUTB1
;-end---PUT_BYTE_1---
SUBI YH,HIGH(BUFFER) ;
ANDI YH,DBMASK_HI ;Y warp
ADDI YH,HIGH(BUFFER) ;
M0: LDI R21,$02
LDI R20,$FF
M1:
M1X: ADD TEMP,TEMP
BRNE M2
ELPM TEMP,Z+
ROL TEMP
M2: ROL R20
BRCC M1X
DEC R21
BRNE X2
LDI DATA,2
ASR R20
BRCS N1
INC DATA
INC R20
BREQ N2
LDI R21,$03
LDI R20,$3F
RJMP M1
X2: DEC R21
BRNE X3
LSR R20
BRCS MS
INC R21
RJMP M1
X6: ADD DATA,R20
N2: LDI R21,$04
LDI R20,$FF
RJMP M1
N1: INC R20
BRNE M4
INC R21
N5: ROR R20
BRCS DEMLZEND
ROL R21
ADD TEMP,TEMP
BRNE N6
ELPM TEMP,Z+
ROL TEMP
N6: BRCC N5
ADD DATA,R21
LDI R21,6
RJMP M1
X3: DEC R21
BRNE X4
LDI DATA,1
RJMP M3
X4: DEC R21
BRNE X5
INC R20
BRNE M4
LDI R21,$05
LDI R20,$1F
RJMP M1
X5: DEC R21
BRNE X6
MOV R21,R20
M4: ELPM R20,Z+
M3: DEC R21
MOV XL,R20
MOV XH,R21
ADD XL,YL
ADC XH,YH
LDIRLOOP:
SUBI XH,HIGH(BUFFER) ;
ANDI XH,DBMASK_HI ;X warp
ADDI XH,HIGH(BUFFER) ;
LD R0,X+
ST Y+,R0
;-begin-PUT_BYTE_2---
OUT SPDR,R0
PUTB2: SBIS SPSR,SPIF
RJMP PUTB2
;-end---PUT_BYTE_2---
SUBI YH,HIGH(BUFFER) ;
ANDI YH,DBMASK_HI ;Y warp
ADDI YH,HIGH(BUFFER) ;
DEC DATA
BRNE LDIRLOOP
RJMP M0
;теперь можно юзать стек
DEMLZEND:
SBIS PINF,CONF_DONE
RJMP DEMLZEND
;SPI reinit
LDI TEMP,(1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)
OUT SPCR,TEMP
SBI PORTE,6
LED_OFF
RCALL NEWLINE
LDIZ MSG_TRYUPDATE*2
RCALL PRINTSTRZ
LDIZ MSG__SDCARD*2
RCALL PRINTSTRZ
;
;--------------------------------------
;инициализация SD карточки
STS SDHC,NULL
SDCS_SET
LDI TEMP,32
RCALL SD_RD_DUMMY
SDCS_CLR
SER COUNT
SDINIT1:LDIZ CMD00*2 ;CMD0 (go_idle_state)
RCALL SD_WR_PGM_6
DEC COUNT
BRNE SDINIT2
LDI DATA,1 ;нет карты
RJMP SD_ERROR
SDINIT2:CPI DATA,$01
BRNE SDINIT1
LDIZ CMD08*2 ;CMD8 (send_if_cond)
RCALL SD_WR_PGM_6
LDI R24,$00
SBRS DATA,2
LDI R24,$40
LDI TEMP,4
RCALL SD_RD_DUMMY
SDINIT3:LDI DATA,$40+55 ;CMD55
RCALL SD_WR_CMD
LDI TEMP,2
RCALL SD_RD_DUMMY
LDI DATA,$40+41 ;ACMD41 (sd_send_op_cond)
RCALL SD_EXCHANGE
MOV DATA,R24
RCALL SD_EXCHANGE
RCALL SD_WR_CMX4
TST DATA
BREQ SDINIT5
SBRS DATA,2
RJMP SDINIT3
SDINIT4:LDI DATA,$40+1 ;CMD1 (send_op_cond)
RCALL SD_WR_CMD
TST DATA
BRNE SDINIT4
RCALL SD_CRC_OFF
;RCALL SD_SETBLKLEN
RJMP SDINIT9
SDINIT5:RCALL SD_CRC_OFF
;RCALL SD_SETBLKLEN
TST R24
BREQ SDINIT9
LDI DATA,$40+58 ;CMD58 (read_ocr)
RCALL SD_WR_CMD
RCALL SD_RECEIVE
STS SDHC,DATA
LDI TEMP,3+2
RCALL SD_RD_DUMMY
SDINIT9:
;
;--------------------------------------
;поиск FAT, инициализация переменных
WC_FAT: LDIX 0
LDIY 0
RCALL LOADLST
RCALL FAT_CHKSIGN
BREQ WC_FAT1
SDERR3: LDI DATA,3 ;не найдена FAT
RJMP SD_ERROR
WC_FAT1:LDI ZL,$BE
LD DATA,Z
ANDI DATA,$7F
BRNE RDFAT05
LDI ZL,$C2
LD DATA,Z
CPI DATA,$01
BREQ RDFAT06
CPI DATA,$04
BREQ RDFAT06
CPI DATA,$06
BREQ RDFAT06
CPI DATA,$0B
BREQ RDFAT06
CPI DATA,$0C
BREQ RDFAT06
CPI DATA,$0E
BRNE RDFAT05
RDFAT06:LDI ZL,$C6
LD XL,Z+
LD XH,Z+
LD YL,Z+
LD YH,Z
RJMP RDFAT00
RDFAT05:LDIZ BUF4FAT
LDD BITS,Z+$0D
LDI DATA,0
LDI TEMP,0
LDI COUNT,8
RDF051: ROR BITS
ADC DATA,NULL
DEC COUNT
BRNE RDF051
DEC DATA
BRNE RDF052
INC TEMP
RDF052: LDD DATA,Z+$0E
LDD R0,Z+$0F
OR DATA,R0
BREQ RDF053
INC TEMP
RDF053: LDD DATA,Z+$13
LDD R0,Z+$14
OR DATA,R0
BRNE RDF054
INC TEMP
RDF054: LDD DATA,Z+$20
LDD R0,Z+$21
OR DATA,R0
LDD R0,Z+$22
OR DATA,R0
LDD R0,Z+$23
OR DATA,R0
BRNE RDF055
INC TEMP
RDF055: LDD DATA,Z+$15
ANDI DATA,$F0
CPI DATA,$F0
BRNE RDF056
INC TEMP
RDF056: CPI TEMP,4
BREQ RDF057
RJMP SDERR3
;
RDF057: LDIY 0
LDIX 0
RDFAT00:STSX STARTRZ+0
STSY STARTRZ+2
RCALL LOADLST
RCALL FAT_CHKSIGN
BREQ RDF011
SDERR3A:RJMP SDERR3
RDF011: LDIZ BUF4FAT
LDD DATA,Z+11 ;BPB_BytsPerSec
TST DATA
BRNE SDERR3A
LDD DATA,Z+12 ;BPB_BytsPerSec
CPI DATA,$02
BRNE SDERR3A
RDF012: LDIY 0
LDD XL,Z+22
LDD XH,Z+23 ;bpb_fatsz16
MOV DATA,XH
OR DATA,XL
BRNE RDFAT01 ;если не fat12/16 (bpb_fatsz16=0)
LDD XL,Z+36 ;то берем bpb_fatsz32 из смещения +36
LDD XH,Z+37
LDD YL,Z+38
LDD YH,Z+39
RDFAT01:STSX SEC_FAT+0
STSY SEC_FAT+2 ;число секторов на fat-таблицу
LDIY 0
LDD XL,Z+19
LDD XH,Z+20 ;bpb_totsec16
MOV DATA,XH
OR DATA,XL
BRNE RDFAT02 ;если не fat12/16 (bpb_totsec16=0)
LDD XL,Z+32 ;то берем из bpb_totsec32 смещения +32
LDD XH,Z+33
LDD YL,Z+34
LDD YH,Z+35
RDFAT02:STSX SEC_DSC+0
STSY SEC_DSC+2 ;к-во секторов на диске/разделе
;вычисляем rootdirsectors
LDD XL,Z+17
LDD XH,Z+18 ;bpb_rootentcnt
LDIY 0
MOV DATA,XH
OR DATA,XL
BREQ RDFAT03
LDI DATA,$10
RCALL BCDE_A
MOVW YL,XL ;это реализована формула
;rootdirsectors = ( (bpb_rootentcnt*32)+(bpb_bytspersec-1) )/bpb_bytspersec
;в Y rootdirsectors
;если fat32, то Y=0 всегда
RDFAT03:PUSH YH
PUSH YL
LDD DATA,Z+16 ;bpb_numfats
STS MANYFAT,DATA
LDSX SEC_FAT+0
LDSY SEC_FAT+2
DEC DATA
RDF031: LSL XL
ROL XH
ROL YL
ROL YH
DEC DATA
BRNE RDF031
POP R24
POP R25
;полный размер fat-области в секторах
RCALL HLDEPBC ;прибавили rootdirsectors
LDD R24,Z+14
LDD R25,Z+15 ;bpb_rsvdseccnt
STS RSVDSEC+0,R24
STS RSVDSEC+1,R25
RCALL HLDEPBC ;прибавили bpb_resvdseccnt
STSX FRSTDAT+0
STSY FRSTDAT+2 ;положили номер первого сектора данных
LDIZ SEC_DSC
RCALL BCDEHLM ;вычли из полного к-ва секторов раздела
LDIZ BUF4FAT
LDD DATA,Z+13
STS BYTSSEC,DATA
RCALL BCDE_A ;разделили на к-во секторов в кластере
STSX CLS_DSC+0
STSY CLS_DSC+2 ;положили кол-во кластеров на разделе
;microsoft-recommended FAT type determination (FAT12 <4085; FAT16 <65525; else FAT32)
LDI DATA,2
TST YH
BRNE RDFAT04
TST YL
BRNE RDFAT04
CPI XL,$F5
CPC XH,FF
BRCC RDFAT04
LDI DATA,1
LDI TEMP,$0F
CPI XL,$F5
CPC XH,TEMP
BRCC RDFAT04
LDI DATA,0
;alternative FAT type determination
; PUSHY
; PUSHX
; LSL XL
; ROL XH
; ROL YL
; ROL YH
; RCALL RASCHET
; LDI DATA,1
; POPX
; POPY
; BREQ RDFAT04
; LSL XL
; ROL XH
; ROL YL
; ROL YH
; LSL XL
; ROL XH
; ROL YL
; ROL YH
; RCALL RASCHET
; LDI DATA,2
; BREQ RDFAT04
; CLR DATA
RDFAT04:STS CAL_FAT,DATA
;для fat12/16 вычисляем адрес первого сектора директории
;для fat32 берем по смещемию +44
;на выходе YX == сектор rootdir
LDIX 0
LDIY 0
TST DATA
BREQ FSRROO2
DEC DATA
BREQ FSRROO2
LDD XL,Z+44
LDD XH,Z+45
LDD YL,Z+46
LDD YH,Z+47
FSRROO2:STSX ROOTCLS+0
STSY ROOTCLS+2 ;сектор root директории
STSX TEK_DIR+0
STSY TEK_DIR+2
FSRR121:PUSHX
PUSHY
LDSX RSVDSEC
LDIY 0
LDIZ STARTRZ
RCALL BCDEHLP
STSX FATSTR0+0
STSY FATSTR0+2
LDIZ SEC_FAT
RCALL BCDEHLP
STSX FATSTR1+0
STSY FATSTR1+2
POPY
POPX
LDI TEMP,1
MOV R0,XL
OR R0,XH
OR R0,YL
OR R0,YH
BREQ LASTCLS
NEXTCLS:PUSH TEMP
RCALL RDFATZP
RCALL LST_CLS
POP TEMP
BRCC LASTCLS
INC TEMP
RJMP NEXTCLS
LASTCLS:STS KCLSDIR,TEMP
LDIY 0
RCALL RDDIRSC
;
;--------------------------------------
;поиск файла в директории
LDIY 0 ;номер описателя файла
RJMP FNDMP32
FNDMP31:ADIW YL,1 ;номер++ ─────────┐
ADIW ZL,$20 ;следующий описатель │
CPI ZH,HIGH(BUF4FAT+512); │
;вылезли за сектор? │
BRNE FNDMP32 ;нет ещё │
RCALL RDDIRSC ;считываем следующий │
BRNE FNDMP37 ;кончились сектора в директории ═│═╗
FNDMP32:LDD DATA,Z+$0B ;атрибуты │ ║
SBRC DATA,3 ;длиное имя/имя диска? │ ║
RJMP FNDMP31 ;да ────────────────────────────┤ ║
SBRC DATA,4 ;директория? │ ║
RJMP FNDMP31 ;да ────────────────────────────┤ ║
LD DATA,Z ;первый символ │ ║
CPI DATA,$E5 ;удалённый файл? │ ║
BREQ FNDMP31 ;да ────────────────────────────┘ ║
TST DATA ;пустой описатель? (конец списка) ╚═ в этой директории
BREQ FNDMP37 ;да ═════════════════════════════════ нет нашёго файла
PUSH ZL
MOVW XL,ZL
LDIZ FILENAME*2
; OUT RAMPZ,ONE
DALSHE: ELPM DATA,Z+
TST DATA
BREQ NASHEL
LD TEMP,X+
CP DATA,TEMP
BREQ DALSHE
;не совпало
MOV ZH,XH
POP ZL
RJMP FNDMP31
;нет такого файла
FNDMP37:
LDI DATA,4 ;нет файла
RJMP SD_ERROR
;найден описатель
NASHEL: MOV ZH,XH
POP ZL
;
;--------------------------------------
;инициализация переменных
;для последующего чтения файла
;Z указывает на описатель файла
LDD XL,Z+$1A
LDD XH,Z+$1B
LDD YL,Z+$14
LDD YH,Z+$15 ;считали номер первого кластера файла
STSX TFILCLS+0
STSY TFILCLS+2
LDD XL,Z+$1C
LDD XH,Z+$1D
LDD YL,Z+$1E
LDD YH,Z+$1F ;считали длину файла
MOV DATA,XL
OR DATA,XH
OR DATA,YL
OR DATA,YH
BRNE F01
RJMP SDUPD_ERR
F01: LDI R24,LOW(511)
LDI R25,HIGH(511)
RCALL HLDEPBC
RCALL BCDE200 ;получили кол-во секторов
SBIW XL,1
SBC YL,NULL
SBC YH,NULL
LDS DATA,BYTSSEC
DEC DATA
AND DATA,XL
INC DATA
STS MPHWOST,DATA ;кол-во секторов в последнем кластере
LDS DATA,BYTSSEC
RCALL BCDE_A
STSX KOL_CLS+0
STSY KOL_CLS+2
STS NUMSECK,NULL
;
;--------------------------------------
;загружаем данные из файла, шьём во флеш
RCALL NEXTSEC
STS LASTSECFLAG,DATA
STS STEP,NULL
LDIY BUFSECT
LDIX HEADER
CLR CRC_LO
CLR CRC_HI
LDI R20,128
SDUPD01:LD DATA,Y+
ST X+,DATA
RCALL CRC_UPDATE
DEC R20
BRNE SDUPD01
OR CRC_LO,CRC_HI
BRNE SDUPD_ERR
RCALL CHECK_SIGNATURE
BRNE SDUPD_ERR
LDI XL,LOW(HEADER+$40)
; LDI XH,HIGH(HEADER+$40)
CLR ADR1
CLR ADR2
SDUPD13:LDI COUNT,8
LD BITS,X+
SDUPD12:LSR BITS
BRCS SDUPD20
;"пустой" блок
MOV FF_FL,FF
RCALL BLOCK_FLASH
BREQ SDUPD50
SDUPD11:LED_OFF
SBRS ADR1,5
LED_ON ;мигать при обновлении
DEC COUNT
BRNE SDUPD12
RJMP SDUPD13
;
SDUPD_ERR:RJMP SDUPD_ERR1
;
;подготавливаем данные
;если необходимо загружаем с SD
SDUPD20:PUSHX
PUSH BITS
PUSH COUNT
LDS DATA,STEP
TST DATA
BRNE SDUPD30
;
LDIY BUFSECT+128
LDIX BUFFER
CLR R20
SDUPD21:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD21
STS STEP,ONE
RJMP SDUPD40
;
SDUPD30:LDIY BUFSECT+384
LDIX BUFFER
LDI R20,128
SDUPD31:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD31
LDS DATA,LASTSECFLAG
TST DATA
BREQ SDUPD_ERR
RCALL NEXTSEC
STS LASTSECFLAG,DATA
STS STEP,NULL
LDIY BUFSECT
LDIX BUFFER+128
LDI R20,128
SDUPD32:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD32
;шьём блок
SDUPD40:POP COUNT
POP BITS
POPX
CLR FF_FL
RCALL BLOCK_FLASH
BRNE SDUPD11
;
SDUPD50:
CLR ADR1
CLR ADR2
SDUPD53:LDI COUNT,8
LD BITS,X+
SDUPD52:LSR BITS
BRCS SDUPD60
;"пустой" блок
RCALL INCEEADR
BREQ SDUPD90
SDUPD51:
DEC COUNT
BRNE SDUPD52
RJMP SDUPD53
;подготавливаем данные
;если необходимо загружаем с SD
SDUPD60:PUSHX
PUSH BITS
PUSH COUNT
LDS DATA,STEP
TST DATA
BRNE SDUPD70
;
LDIY BUFSECT+128
LDIX BUFFER
CLR R20
SDUPD61:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD61
STS STEP,ONE
RJMP SDUPD80
SDUPD70:LDIY BUFSECT+384
LDIX BUFFER
LDI R20,128
SDUPD71:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD71
LDS DATA,LASTSECFLAG
TST DATA
BREQ SDUPD_ERR1
RCALL NEXTSEC
STS LASTSECFLAG,DATA
STS STEP,NULL
LDIY BUFSECT
LDIX BUFFER+128
LDI R20,128
SDUPD72:LD DATA,Y+
ST X+,DATA
DEC R20
BRNE SDUPD72
;пишем блок EEPROM
SDUPD80:POP COUNT
POP BITS
POPX
RCALL BLOCK_EEWRITE
BRNE SDUPD51
SDUPD90:RJMP CHECKIT ;проверка CRC основной программы и если всё Ok её запуск.
;
SDUPD_ERR1:
LDI DATA,5 ;ошибка в файле (CRC/signature/length)
;
;--------------------------------------
;ошибка при попытке обновления с SD
SD_ERROR:
STS SDERROR,DATA
SDCS_SET
LDI TEMP,LOW(RAMEND)
OUT SPL,TEMP
LDI TEMP,HIGH(RAMEND)
OUT SPH,TEMP
RCALL NEWLINE
LDIZ MSG_SDERROR*2
RCALL PRINTSTRZ
LDI DATA,ANSI_RED
RCALL ANSI_COLOR
LDS DATA,SDERROR
CPI DATA,1
BRNE SD_ERR2
LDIZ MSG_CARD*2
RCALL PRINTSTRZ
RJMP SD_NOTFOUND
SD_ERR2:
CPI DATA,2
BRNE SD_ERR3
LDIZ MSG_READERROR*2
RCALL PRINTSTRZ
RJMP SD_ERR9
SD_ERR3:
CPI DATA,3
BRNE SD_ERR4
LDIZ MSG_FAT*2
RCALL PRINTSTRZ
RJMP SD_NOTFOUND
SD_ERR4:
CPI DATA,4
BRNE SD_ERR5
LDIZ MSG_FILE*2
RCALL PRINTSTRZ
SD_NOTFOUND:
LDIZ MSG_NOTFOUND*2
RCALL PRINTSTRZ
RJMP SD_ERR9
SD_ERR5:
LDIZ MSG_WRONGFILE*2
RCALL PRINTSTRZ
SD_ERR9:
;
LDS ZL,SDERROR
SD_ERR1:LED_OFF
LDI DATA,5
RCALL BEEP
LED_ON
LDI DATA,5
RCALL DELAY
DEC ZL
BRNE SD_ERR1
;обновление по RS-232
;UART1 Разрешаем приём/передачу
LDI TEMP,(1<<RXEN)|(1<<TXEN)
OUTPORT UCSR1B,TEMP
;
RCALL NEWLINE
LDIZ MSG_TRYUPDATE*2
RCALL PRINTSTRZ
LDIZ MSG__RS232*2
RCALL PRINTSTRZ
;инициируем обмен по протоколу XModem-CRC
LDI TEMP,20 ;если в течении ~60 секунд не начнётся обмен - будет перезагрузка бутлоадера (20*timeout=60)
UUPD00: PUSH TEMP
LDI DATA,$43
LDIY HEADER
RCALL XMODEM_PACKET_RECEIVER
POP TEMP
BRNE UUPD01
DEC TEMP
BRNE UUPD00
RJMP START8 ;проверка CRC основной программы и если всё Ok её запуск.
UUPD01: OR CRC_LO,CRC_HI
BREQ UUPD03
UUPD04:
LDI DATA,CAN
RCALL WRUART
RCALL WRUART
RCALL WRUART
RCALL WRUART
RCALL WRUART
RCALL DELAY_3SEC
LDIZ MSG_CLRCURRLINE*2
RCALL PRINTSTRZ
RCALL NEWLINE
LDI DATA,ANSI_RED
RCALL ANSI_COLOR
LDIZ MSG_WRONGDATA*2
RCALL PRINTSTRZ
RCALL DELAY_3SEC
RJMP START8 ;проверка CRC основной программы и если всё Ok её запуск.
UUPD03:
RCALL CHECK_SIGNATURE
BRNE UUPD04
;-------
LDI XL,LOW(HEADER+$40)
; LDI XH,HIGH(HEADER+$40)
CLR ADR1
CLR ADR2
UUPD13: LDI COUNT,8
LD BITS,X+
UUPD12: LSR BITS
BRCS UUPD14
;пропускаем "пустой" блок
RCALL INCADR
BREQ UUPD20
UUPD11: DEC COUNT
BRNE UUPD12
RJMP UUPD13
;загружаем блок
UUPD14: LDIY BUFFER
LDI DATA,ACK
UUPD15: RCALL XMODEM_PACKET_RECEIVER
BRNE UUPD16
CPI DATA,EOT
BREQ UUPD19
LDI DATA,NAK
RJMP UUPD15
UUPD16: LDI DATA,ACK
UUPD17: RCALL XMODEM_PACKET_RECEIVER
BRNE UUPD18
CPI DATA,EOT
BREQ UUPD19
LDI DATA,NAK
RJMP UUPD17
UUPD19: RJMP UUPD_F3
;шьём принятый блок (два XModem-ых пакета по 128 байт)
UUPD18: CLR FF_FL
RCALL BLOCK_FLASH
BRNE UUPD11
;-------
UUPD20:
LDI XL,LOW(HEADER+$40)
; LDI XH,HIGH(HEADER+$40)
CLR ADR1
CLR ADR2
UUPD23: LDI COUNT,8
LD BITS,X+
UUPD22: LSR BITS
BRCC UUPD24
;пропускаем блок
RCALL INCADR
BREQ UUPD30
UUPD21: DEC COUNT
BRNE UUPD22
RJMP UUPD23
;стираем "пустой" блок
UUPD24: MOV FF_FL,FF
RCALL BLOCK_FLASH
BRNE UUPD21
;-------
UUPD30: CLR ADR1
CLR ADR2
UUPD33: LDI COUNT,8
LD BITS,X+
UUPD32: LSR BITS
BRCS UUPD34
;пропускаем "пустой" блок
RCALL INCEEADR
BREQ UUPD_FINISH
UUPD31: DEC COUNT
BRNE UUPD32
RJMP UUPD33
;загружаем блок
UUPD34: LDIY BUFFER
LDI DATA,ACK
UUPD35: RCALL XMODEM_PACKET_RECEIVER
BRNE UUPD36
CPI DATA,EOT
BREQ UUPD39
LDI DATA,NAK
RJMP UUPD35
UUPD36: LDI DATA,ACK
UUPD37: RCALL XMODEM_PACKET_RECEIVER
BRNE UUPD38
CPI DATA,EOT
BREQ UUPD39
LDI DATA,NAK
RJMP UUPD37
UUPD39: RJMP UUPD_F3
;пишем в EEPROM принятый блок (два XModem-ых пакета по 128 байт)
UUPD38: RCALL BLOCK_EEWRITE
BRNE UUPD31
;-------
UUPD_FINISH:
LDI DATA,ACK
RCALL WRUART
RCALL RDUART
UUPD_F3:CPI DATA,EOT ; обязательно должно придти EOT
LDI DATA,ACK
BREQ UUPD_F1
UUPD_F2:LDI DATA,CAN
RCALL WRUART
RCALL WRUART
RCALL WRUART
RCALL WRUART
UUPD_F1:RCALL WRUART
RCALL DELAY_3SEC
LDIZ MSG_CLRCURRLINE*2
RCALL PRINTSTRZ
RJMP CHECKIT ;проверка CRC основной программы и если всё Ok её запуск.
;
;--------------------------------------
;XMODEM_PACKET_RECEIVER
;in: DATA == <C>, <NAK> или <ACK>
; Y == указатель на буфер
;out: sreg.Z == SET - timeout (Y без изменений)
; CLR - Ok! (Y=+128)
XMRXERR:SUBI YL,128
SBC YH,NULL
LDI DATA,NAK
;
XMODEM_PACKET_RECEIVER:
RCALL WRUART
LDI TEMP,6 ;таймаут 3 сек.
XMRX3: LED_OFF
SBRC TEMP,0
LED_ON ;мигать при ожидании
LDI R20,$00 ;\
LDI R21,$70 ; > ~0,5 сек
LDI ZL,$05 ;/
XMRX1: SUBI R20,1
SBCI R21,0
SBCI ZL,0
BRNE XMRX2
DEC TEMP
BRNE XMRX3
CLR DATA
XMRX9: RET
XMRX2: RCALL INUART
BREQ XMRX1
CPI DATA,EOT
BREQ XMRX9
CPI DATA,SOH
BRNE XMRX1
LED_OFF
SBRS ADR1,1
LED_ON
RCALL RDUART ;block num
RCALL RDUART ;block num (inverted)
CLR CRC_LO
CLR CRC_HI
LDI R20,128
XMRX4: RCALL RDUART
ST Y+,DATA
RCALL CRC_UPDATE
DEC R20
BRNE XMRX4
RCALL RDUART
MOV TEMP,DATA
RCALL RDUART
CP DATA,CRC_LO
BRNE XMRXERR
CP TEMP,CRC_HI
BRNE XMRXERR
CLZ
RET
;
;--------------------------------------
;
CHECK_SIGNATURE:
LDIZ SIGNATURE*2
OUT RAMPZ,ONE
LDIX HEADER
CHKSIG1:ELPM DATA,Z+
LD TEMP,X+
CP DATA,TEMP
BRNE CHKSIG9
CPI DATA,$1A
BRNE CHKSIG1
CHKSIG9:RET
;
;======================================
;out: DATA
SD_RECEIVE:
SER DATA
; - - - - - - - - - - - - - - - - - - -
;in: DATA
;out: DATA
SD_EXCHANGE:
OUT SPDR,DATA
SDEXCH: SBIS SPSR,SPIF
RJMP SDEXCH
IN DATA,SPDR
RET
;
;--------------------------------------
;in; TEMP - n
SD_RD_DUMMY:
SER DATA
RCALL SD_EXCHANGE
DEC TEMP
BRNE SD_RD_DUMMY
RET
;
;--------------------------------------
;in: DATA
SD_WR_CMD:
PUSH DATA
LDI TEMP,2
RCALL SD_RD_DUMMY
POP DATA
RCALL SD_EXCHANGE
CLR DATA
RCALL SD_EXCHANGE
SD_WR_CMX4:
CLR DATA
RCALL SD_EXCHANGE
CLR DATA
RCALL SD_EXCHANGE
CLR DATA
RCALL SD_EXCHANGE
SER DATA
RCALL SD_EXCHANGE
RJMP SD_WAIT_NOTFF
;
;--------------------------------------
;in: Z
SD_WR_PGM_6:
LDI TEMP,2
RCALL SD_RD_DUMMY
LDI TEMP,6
SD_WR_PGX:
OUT RAMPZ,ONE
SDWRP61:ELPM DATA,Z+
RCALL SD_EXCHANGE
DEC TEMP
BRNE SDWRP61
; - - - - - - - - - - - - - - - - - - -
;out: DATA
SD_WAIT_NOTFF:
LDI TEMP,255
SDWNFF2:SER DATA
RCALL SD_EXCHANGE
CPI DATA,$FF
BRNE SDWNFF1
DEC TEMP
BRNE SDWNFF2
SDWNFF1:RET
;
;--------------------------------------
;in: Z - куда
; Y,X - №сектора
SD_READ_SECTOR:
SDCS_CLR
PUSHZ
LDS DATA,SDHC
SBRC DATA,6
RJMP SDRDSE1
LSL XL
ROL XH
ROL YL
MOV YH,YL
MOV YL,XH
MOV XH,XL
CLR XL
SDRDSE1:
LDI TEMP,3+2
RCALL SD_RD_DUMMY
LDI DATA,CMD_17
RCALL SD_EXCHANGE
MOV DATA,YH
RCALL SD_EXCHANGE
MOV DATA,YL
RCALL SD_EXCHANGE
MOV DATA,XH
RCALL SD_EXCHANGE
MOV DATA,XL
RCALL SD_EXCHANGE
SER DATA
RCALL SD_EXCHANGE
SER R24
SDRDSE2:RCALL SD_WAIT_NOTFF
DEC R24
BREQ SDRDSE8
CPI DATA,$FE
BRNE SDRDSE2
POPZ
LDI R24,$00
LDI R25,$02
SDRDSE3:RCALL SD_RECEIVE
ST Z+,DATA
SBIW R24,1
BRNE SDRDSE3
LDI TEMP,2+2
RCALL SD_RD_DUMMY
;SDRDSE4:RCALL SD_WAIT_NOTFF
; CPI DATA,$FF
; BRNE SDRDSE4
SDCS_SET
RET
SDRDSE8:LDI DATA,2 ;ошибка при чтении сектора
RJMP SD_ERROR
;
;--------------------------------------
;
SD_CRC_OFF:
LDI DATA,$40+59 ;CMD59 (crc_on_off)
RCALL SD_WR_CMD
TST DATA
BRNE SD_CRC_OFF
; RET
SD_SETBLKLEN:
LDIZ CMD16*2 ;CMD16 (set_blocklen)
RCALL SD_WR_PGM_6
TST DATA
BRNE SD_SETBLKLEN
RET
;
;--------------------------------------
;out: sreg.Z SET==signature exist
; Z==BUF4FAT+$01FF
FAT_CHKSIGN:
LDIZ BUF4FAT+$01FE
LD DATA,Z+
CPI DATA,$55
LD DATA,Z
BRNE FAT_CHKSIG9
CPI DATA,$AA
FAT_CHKSIG9:
RET
;
;--------------------------------------
;чтение сектора данных
LOAD_DATA:
LDIZ BUFSECT
RCALL SD_READ_SECTOR ;читать один сектор
RET
;
;--------------------------------------
;чтение сектора служ.инф. (FAT/DIR/...)
LOADLST:LDIZ BUF4FAT
RCALL SD_READ_SECTOR ;читать один сектор
LDIZ BUF4FAT
RET
;
;--------------------------------------
;чтение сектора dir по номеру описателя (Y)
;на выходе: DATA=#ff (sreg.Z=0) выход за пределы dir
RDDIRSC:PUSHY
MOVW XL,YL
LDIY 0
LDI DATA,$10
RCALL BCDE_A
PUSH XL
LDS DATA,BYTSSEC
PUSH DATA
RCALL BCDE_A
LDS DATA,KCLSDIR
DEC DATA
CP DATA,XL
BRCC RDDIRS3
POP YL
POP YL
POPY
SER DATA
TST DATA
RET
RDDIRS3:LDSY TEK_DIR+2
MOV DATA,XL
TST DATA
LDSX TEK_DIR+0
BREQ RDDIRS1
RDDIRS2:PUSH DATA
RCALL RDFATZP
POP DATA
DEC DATA
BRNE RDDIRS2
RDDIRS1:RCALL REALSEC
POP R0
DEC R0
POP DATA
AND DATA,R0
ADD XL,DATA
ADC XH,NULL
ADC YL,NULL
ADC YH,NULL
RCALL LOADLST
POPY
CLR DATA
RET
;
;--------------------------------------
;out: sreg.C == CLR - EOCmark
;(chng: TEMP)
LST_CLS:LDI TEMP,$0F
LDS DATA,CAL_FAT
TST DATA
BRNE LST_CL1
CPI XL,$F7
CPC XH,TEMP
RET
LST_CL1:DEC DATA
BRNE LST_CL2
CPI XL,$F7
CPC XH,FF
RET
LST_CL2:CPI XL,$F7
CPC XH,FF
CPC YL,FF
CPC YH,TEMP
RET
;
;--------------------------------------
;
RDFATZP:LDS DATA,CAL_FAT
TST DATA
BREQ RDFATS0 ;FAT12
DEC DATA
BREQ RDFATS1 ;FAT16
;FAT32
LSL XL
ROL XH
ROL YL
ROL YH
MOV DATA,XL
MOV XL,XH
MOV XH,YL
MOV YL,YH
CLR YH
RCALL RDFATS2
ADIW ZL,1
LD YL,Z+
LD YH,Z
ANDI YH,$0F ;
RET
;FAT16
RDFATS1:LDIY 0
MOV DATA,XL
MOV XL,XH
CLR XH
RDFATS2:PUSH DATA
PUSHY
LDIZ FATSTR0
RCALL BCDEHLP
RCALL LOADLST
POPY
POP DATA
ADD ZL,DATA
ADC ZH,NULL
ADD ZL,DATA
ADC ZH,NULL
LD XL,Z+
LD XH,Z
RET
;FAT12
RDFATS0:MOVW ZL,XL
LSL ZL
ROL ZH
ADD ZL,XL
ADC ZH,XH
LSR ZH
ROR ZL
MOV DATA,XL
MOV XL,ZH
CLR XH
CLR YL
CLR YH
LSR XL
PUSH DATA
PUSHZ
LDIZ FATSTR0
RCALL BCDEHLP
PUSHX
RCALL LOADLST
POPX
POPY
ANDI YH,$01
ADD ZL,YL
ADC ZH,YH
LD YL,Z+
CPI ZH,HIGH(BUF4FAT+512)
BRNE RDFATS4
PUSH YL
LDIY 0
ADIW XL,1
RCALL LOADLST
POP YL
RDFATS4:POP DATA
LD XH,Z
MOV XL,YL
LDIY 0
LSR DATA
BRCC RDFATS3
LSR XH
ROR XL
LSR XH
ROR XL
LSR XH
ROR XL
LSR XH
ROR XL
RDFATS3:ANDI XH,$0F
RET
;
;--------------------------------------
;вычисление реального сектора
;на входе YX==номер FAT
;на выходе YX==адрес сектора
REALSEC:MOV DATA,YH
OR DATA,YL
OR DATA,XH
OR DATA,XL
BRNE REALSE1
LDIZ FATSTR1
LDSX SEC_FAT+0
LDSY SEC_FAT+2
RJMP BCDEHLP
REALSE1:SBIW XL,2 ;номер кластера-2
SBC YL,NULL
SBC YH,NULL
LDS DATA,BYTSSEC
RJMP REALSE2
REALSE3:LSL XL
ROL XH
ROL YL
ROL YH
REALSE2:LSR DATA
BRCC REALSE3
;умножили на размер кластера
LDIZ STARTRZ
RCALL BCDEHLP ;прибавили смещение от начала диска
LDIZ FRSTDAT
RJMP BCDEHLP ;прибавили смещение от начала раздела
;
;--------------------------------------
;YX>>9 (деление на 512)
BCDE200:MOV XL,XH
MOV XH,YL
MOV YL,YH
LDI YH,0
LDI DATA,1
; - - - - - - - - - - - - - - - - - - -
;YXDATA>>до"переноса"
;если в DATA вкл.только один бит, то получается
;YX=YX/DATA
BCDE_A1:LSR YH
ROR YL
ROR XH
ROR XL
BCDE_A: ROR DATA
BRCC BCDE_A1
RET
;
;--------------------------------------
;YX=[Z]-YX
BCDEHLM:LD DATA,Z+
SUB DATA,XL
MOV XL,DATA
LD DATA,Z+
SBC DATA,XH
MOV XH,DATA
LD DATA,Z+
SBC DATA,YL
MOV YL,DATA
LD DATA,Z
SBC DATA,YH
MOV YH,DATA
RET
;
;--------------------------------------
;YX=YX+[Z]
BCDEHLP:LD DATA,Z+
ADD XL,DATA
LD DATA,Z+
ADC XH,DATA
LD DATA,Z+
ADC YL,DATA
LD DATA,Z
ADC YH,DATA
RET
;
;--------------------------------------
;YX=YX+R25R24
HLDEPBC:ADD XL,R24
ADC XH,R25
ADC YL,NULL
ADC YH,NULL
RET
;
;--------------------------------------
;
RASCHET:RCALL BCDE200
LDIZ SEC_FAT
RCALL BCDEHLM
MOV DATA,XL
ANDI DATA,$F0
OR DATA,XH
OR DATA,YL
OR DATA,YH
RET
;
;--------------------------------------
;чтение очередного сектора файла в BUFSECT
;out: DATA == 0 - считан последний сектор файла
NEXTSEC:LDIZ KOL_CLS
LD DATA,Z+
LD TEMP,Z+
OR DATA,TEMP
LD TEMP,Z+
OR DATA,TEMP
LD TEMP,Z+
OR DATA,TEMP
BREQ LSTCLSF
LDSX TFILCLS+0
LDSY TFILCLS+2
RCALL REALSEC
LDS DATA,NUMSECK
ADD XL,DATA
ADC XH,NULL
ADC YL,NULL
ADC YH,NULL
RCALL LOAD_DATA
LDSX TFILCLS+0
LDSY TFILCLS+2
LDS DATA,NUMSECK
INC DATA
STS NUMSECK,DATA
LDS TEMP,BYTSSEC
CP TEMP,DATA
BRNE NEXT_OK
STS NUMSECK,NULL
RCALL RDFATZP
STSX TFILCLS+0
STSY TFILCLS+2
LDIZ KOL_CLS
LD DATA,Z
SUBI DATA,1
ST Z+,DATA
LD DATA,Z
SBC DATA,NULL
ST Z+,DATA
LD DATA,Z
SBC DATA,NULL
ST Z+,DATA
LD DATA,Z
SBC DATA,NULL
ST Z+,DATA
NEXT_OK:SER DATA
RET
LSTCLSF:LDSX TFILCLS+0
LDSY TFILCLS+2
RCALL REALSEC
LDS DATA,NUMSECK
ADD XL,DATA
ADC XH,NULL
ADC YL,NULL
ADC YH,NULL
RCALL LOAD_DATA
LDS DATA,NUMSECK
INC DATA
STS NUMSECK,DATA
LDS TEMP,MPHWOST
SUB DATA,TEMP
RET
;
;======================================
;
PRINTVERS:
LDI DATA,ANSI_GREEN
RCALL ANSI_COLOR
LDI COUNT,12
PRVERS2:ELPM DATA,Z+
TST DATA
BREQ PRVERS1
BRMI PRVERS1
RCALL WRUART
DEC COUNT
BRNE PRVERS2
PRVERS1:LDI DATA,$20
RCALL WRUART
LDI ZL,$FC
ELPM XL,Z+
ELPM XH,Z+
MOV DATA,XL
ANDI DATA,$1F
BREQ PRVERS9
MOV TEMP,XH
LSL XL
ROL TEMP
LSL XL
ROL TEMP
LSL XL
ROL TEMP
ANDI TEMP,$0F
BREQ PRVERS9
CPI TEMP,13
BRCC PRVERS9
MOV COUNT,XH
LSR COUNT
ANDI COUNT,$3F
CPI COUNT,9
BRCS PRVERS9
RCALL DECBYTE
LDI DATA,$2E
RCALL WRUART
MOV DATA,TEMP
RCALL DECBYTE
LDI DATA,$2E
RCALL WRUART
LDI DATA,$20
RCALL HEXBYTE
MOV DATA,COUNT
RCALL DECBYTE
SBRC XH,7
PRVERS9:RET
;
;--------------------------------------
;
BETA: LDIZ MSG_BETA*2
RJMP PRINTSTRZ
;
;--------------------------------------
;
ANSI_COLOR:
PUSH DATA
LDI DATA,$1B
RCALL WRUART
LDI DATA,$5B
RCALL WRUART
POP DATA
RCALL HEXBYTE
LDI DATA,$6D
RJMP WRUART
;
;--------------------------------------
;
NEWLINE2:
LDIZ MSG_NEWLINE2*2
RJMP PRINTSTRZ
;
NEWLINE:LDIZ MSG_NEWLINE*2
;
; - - - - - - - - - - - - - - - - - - -
;in: Z == указательна строку (в старших 64K)
PRINTSTRZ:
OUT RAMPZ,ONE
PRSTRZ1:ELPM DATA,Z+
TST DATA
BREQ PRSTRZ2
RCALL WRUART
RJMP PRSTRZ1
PRSTRZ2:RET
;
;--------------------------------------
;byte in dec to uart
;in: DATA == byte (0..99)
DECBYTE:SUBI DATA,208
SBRS DATA,7
SUBI DATA,48
SUBI DATA,232
SBRS DATA,6
SUBI DATA,24
SUBI DATA,244
SBRS DATA,5
SUBI DATA,12
SUBI DATA,250
SBRS DATA,4
SUBI DATA,6
;
; - - - - - - - - - - - - - - - - - - -
;byte in hex to uart
;in: DATA == byte
HEXBYTE:PUSH DATA
SWAP DATA
RCALL HEXHALF
POP DATA
HEXHALF:ANDI DATA,$0F
CPI DATA,$0A
BRCS HEXBYT1
ADDI DATA,$07
HEXBYT1:ADDI DATA,$30
;
; - - - - - - - - - - - - - - - - - - -
;in: DATA == передаваемый байт
WRUART: PUSH TEMP
WRU_1: INPORT TEMP,UCSR1A
SBRS TEMP,UDRE
RJMP WRU_1
OUTPORT UDR1,DATA
POP TEMP
RET
;
;--------------------------------------
;out: DATA == принятый байт
RDUART: INPORT DATA,UCSR1A
SBRS DATA,RXC
RJMP RDUART
INPORT DATA,UDR1
RET
;
;--------------------------------------
;out: sreg.Z == CLR - есть данные (DATA == принятый байт)
; SET - нет данных
INUART: INPORT DATA,UCSR1A
SBRS DATA,RXC
RJMP INU9
INPORT DATA,UDR1
CLZ
INU9: RET
;
;--------------------------------------
;in: DATA == продолжительность *0.1 сек
BEEP: OUT SPCR,NULL ;SPI off
BEE2: LDI TEMP,100;100 периодов 1кГц
BEE1: SBI DDRE,6
CBI PORTE,6
RCALL BEEPDLY
CBI DDRE,6
SBI PORTE,6
RCALL BEEPDLY
DEC TEMP
BRNE BEE1
DEC DATA
BRNE BEE2
RET
BEEPDLY:LDI R24,$64
LDI R25,$05
BEEPDL1:SBIW R24,1
BRNE BEEPDL1
RET
;
;--------------------------------------
;
DELAY_3SEC:
LDI DATA,30
; - - - - - - - - - - - - - - - - - - -
;in: DATA == продолжительность *0.1 сек
DELAY:
LDI R20,$1E ;\
LDI R21,$FE ;/ 0,1 сек @ 11.0592MHz
DELAY1: LPM ;3
LPM ;3
LPM ;3
LPM ;3
SUBI R20,1 ;1
SBCI R21,0 ;1
SBCI DATA,0 ;1
BRNE DELAY1 ;2(1)
RET
;
;--------------------------------------
;проверка CRC осн.программы
CRCMAIN:LDIZ $0000 ;адрес в байтах
OUT RAMPZ,NULL
LDIY FLASHSIZE<<7 ;длина в словах
; - - - - - - - - - - - - - - - - - - -
;in: Z == адрес в байтах
; Y == кол-во слов
;out: sreg.Z == SET - crc ok!
CALK_CRC_FLASH:
MOV CRC_LO,FF
MOV CRC_HI,FF
CCRCFL1:ELPM DATA,Z+
RCALL CRC_UPDATE
ELPM DATA,Z+
RCALL CRC_UPDATE
LED_OFF
SBRS ZH,5
LED_ON ;мигать при подсчёте CRC
SBIW YL,1
BRNE CCRCFL1
OR CRC_LO,CRC_HI
RET
;
;--------------------------------------
;in: DATA - byte
; CRC_LO,CRC_HI
;out: CRC_LO,CRC_HI
;cng: TEMP
CRC_UPDATE:
EOR CRC_HI,DATA
LDI TEMP,8
CRC_UP2:LSL CRC_LO
ROL CRC_HI
BRCC CRC_UP1
EOR CRC_LO,POLY_LO
EOR CRC_HI,POLY_HI
CRC_UP1:DEC TEMP
BRNE CRC_UP2
RET
;
;--------------------------------------
;in: [BUFFER] == data
; ADR1 == mid address
; ADR2 == high address
; FF_FL == $FF - erase only
;out: sreg.Z == SET - это был последний блок (выше по адресам обновлять запрещено!)
; ADR1 == mid address
; ADR2 == high address
BLOCK_FLASH:
CLR ZL
MOV ZH,ADR1
OUT RAMPZ,ADR2
LDI GUARD,$A5
LDI DATA,(1<<PGERS)|(1<<SPMEN) ;page erase
RCALL DO_SPM
INC FF_FL
BREQ BLKFL1
CLR ZL
MOV ZH,ADR1
OUT RAMPZ,ADR2
LDIY BUFFER
LDI TEMP,$80
BLKFL2: LD R0,Y+
LD R1,Y+
LDI DATA,(1<<SPMEN) ;transfer data from RAM to Flash page buffer
RCALL DO_SPM
ADIW ZL,2
DEC TEMP
BRNE BLKFL2
CLR ZL
MOV ZH,ADR1
OUT RAMPZ,ADR2
LDI DATA,(1<<PGWRT)|(1<<SPMEN) ;execute page write
RCALL DO_SPM
BLKFL1:
LDI DATA,(1<<RWWSRE)|(1<<SPMEN) ;re-enable the RWW section
RCALL DO_SPM
LDI GUARD,$5A
TST FF_FL
BREQ INCADR
LDIY BUFFER
CLR ZL
MOV ZH,ADR1
OUT RAMPZ,ADR2
CLR R20
BLKFL3: ELPM DATA,Z+
LD TEMP,Y+
CP DATA,TEMP
BRNE FLASH_ERROR
DEC R20
BRNE BLKFL3
;
;--------------------------------------
;out: sreg.Z == SET - это был последний блок (выше по адресам обновлять запрещено!)
;chng: TEMP
INCADR:
ADD ADR1,ONE
ADC ADR2,NULL
MOV TEMP,ADR2
CPI TEMP,HIGH(FLASHSIZE)
BRNE INCADR9
MOV TEMP,ADR1
CPI TEMP,LOW(FLASHSIZE)
INCADR9:RET
;
;--------------------------------------
;in: [BUFFER] == data
; ADR1 == low address
; ADR2 == high address
;out: sreg.Z == SET - это был последний блок (выше по адресам обновлять запрещено!)
; ADR1 == low address
; ADR2 == high address
BLOCK_EEWRITE:
LDIY BUFFER
LDI GUARD,$A5
WEEWE: SBIC EECR,EEWE
RJMP WEEWE
WSPMEN: LDS TEMP,SPMCSR
SBRC TEMP,SPMEN
RJMP WSPMEN
OUT EEARH,ADR2
OUT EEARL,ADR1
LD DATA,Y+
OUT EEDR,DATA
CPI GUARD,$A5
BRNE CRITICAL_ERROR
SBI EECR,EEMWE
SBI EECR,EEWE
LED_OFF
SBRS ADR1,4
LED_ON ;мигать при записи EEPROM
INC ADR1
BRNE WEEWE
LDI GUARD,$5A
;
;--------------------------------------
;out: sreg.Z == SET - это был последний блок (выше по адресам обновлять запрещено!)
;chng: TEMP
INCEEADR:
ADD ADR2,ONE
MOV TEMP,ADR2
CPI TEMP,HIGH(4096)
RET
;
;--------------------------------------
;
FLASH_ERROR:
LDI DATA,30
RCALL BEEP
CRITICAL_ERROR:
RJMP START1
;
;--------------------------------------
;in: DATA == значение для SPMCSR
DO_SPM: PUSH TEMP
WAIT1SPM: ; check for previous SPM complete
INPORT TEMP,SPMCSR
SBRC TEMP,SPMEN
RJMP WAIT1SPM
CLI
WAIT_EE:SBIC EECR,EEWE ; check that no EEPROM write access is present
RJMP WAIT_EE
OUTPORT SPMCSR,DATA ; SPM timed sequence
CPI GUARD,$A5 ;1
BRNE CRITICAL_ERROR ;1
SPM
NOP
NOP
NOP
NOP
WAIT2SPM: ; check for previous SPM complete
INPORT TEMP,SPMCSR
SBRC TEMP,SPMEN
RJMP WAIT2SPM
POP TEMP
RET
;
;--------------------------------------
;
CMD00: .DB $40,$00,$00,$00,$00,$95
CMD08: .DB $48,$00,$00,$01,$AA,$87
CMD16: .DB $50,$00,$00,$02,$00,$FF
FILENAME: .DB "ZXEVO_FWBIN",0
SIGNATURE: .DB "ZXEVO",$1A
MSG_NEWLINE2:
.DB $0D,$0A
MSG_NEWLINE:
.DB $0D,$0A,$1B,"[1",$3B,"37m",0
MSG_BADCRC:
.DB $1B,"[31mBad CRC!",0
MSG_BOOT:
.DB "boot: ",0,0
MSG_BETA:
.DB " beta",0
MSG_MAIN:
.DB "main: ",0,0
MSG_SDERROR:
.DB "SD error: ",0,0
MSG_CARD:
.DB "Card",0,0
MSG_READERROR:
.DB "Read error",0,0
MSG_FAT:
.DB "FAT",0
MSG_FILE:
.DB "File",0,0
MSG_WRONGFILE:
.DB "Wrong file",0,0
MSG_NOTFOUND:
.DB " not found",0,0
MSG_CFGFPGA:
.DB $0D,$0A,"Set temporary configuration...",0,0
MSG_TRYUPDATE:
.DB "Try update from ",0,0
MSG__SDCARD:
.DB "SD-card...",0,0
MSG__RS232:
.DB "RS-232...",$0D,$0A,$1B,"[0mNow, start file transfer using X-Modem-CRC protocol. ",$1B,"[30m",0
MSG_CLRCURRLINE:
.DB $0D,$1B,"[K",0,0
MSG_WRONGDATA:
.DB "Data is corrupt! Update is canceled.",0,0
MSG_RECHECK:
.DB "Recheck flash... ",0
MSG_MAINOK:
.DB "Ok!",0
MSG_MAINBAD:
.DB "Update is failure.",0,0
MSG_TITLE:
.INCLUDE "evotitle.inc"
;
PACKED_FPGA:
.NOLIST
.INCLUDE "fpga.inc"
.LIST
;
;--------------------------------------
;
.ORG FLASHEND-$0007
BOOT_VERS:
.DW 0,0,0,0,0,0 ;здесь будет строчка описателя bootloader-а
.DW 0 ;здесь будет дата(версия) bootloader-а
.DW 0 ;здесь будет CRC bootloader-а
BOOTLOADER_END: