ds30 bootloader ds30loader.asm
Ook hier een 18F25K20 met interne oscillator op 8Mhz
Bij lijn nr. 233 vindt je het vak “User specific entry code go here”
Hier kun je diverse register instellingen kwijt die nodig zijn om de communicatie poorten op de juiste manier in te stellen.
Om de interne oscillator van de 18F25K20 op 8Mhz te krijgen moet je het OSCCON register instellen (zie datasheet)
Zonder ingesteld register werkt de oscillator op 1 Mhz.
Zie bij lijn 255 hoe je dit doet.
Een andere vaak voorkomende instelling die je moet doen is het van analoog naar digitaal zetten van de voor communicatie bedoelde poorten.
Bij alle PIC’s is het zo dat poorten die een analoge functie kunnen hebben, bij het opstarten als analoog (input) op komen, je kunt er op dat moment dus niet mee communiceren.(ontvangen)
Bij de 18F25K20 is dit niet nodig omdat C7 (RX) geen analoge functie heeft.
Bij de 18F25K22 moet dit wel!
De error lijn (lijn 240) die in werking treed zodra er sprake is van een device met een ADCON1 register (betekend dat de PIC analoge functies heeft) komt op, ongeacht of dat die functies op de communicatie poorten zitten.
Na controle of verdere acties nodig zijn moet deze lijn uitgecommentarieerd worden (; ervoor) zodat de uiteindelijke hex file gemaakt kan worden (build).
Met een error melding erin gaat dit niet.
;------------------------------------------------------------------------------
;
; Title: ds30 Loader for PIC18F
;
; File description: Main firmwarefile
;
; Copyright: Copyright � 09-11, Mikael Gustafsson
;
; Version: 3.0.0 April 2011
;
; Webpage: http://mrmackey.no-ip.org/elektronik/ds30loader/
;
; Thanks to: Claudio Chiculita, this code is based on the Tiny PIC bootloader
; Fabien Pieraldi for writing the CAN part
;
; History: 3.0.0 New feature: compatible with ds30 Secure Loader
; New feature: auto baud rate detection
; Bugifx: bootloader protection was calculate wrong on PIC18F devices with 64 byte pagesize
; Bugfix: receiving non hello command on start-up caused long delay
; Improvement: merged PIC18FJ firmware
; Improvement: increased range of timeout values
; 2.0.5 Bugfix: devices with pagesize != 32 words
; 2.0.4 Bugfix: uart 1 rx interupt flag was checked also for uart 2
; New feature: 16-bit brg
; 2.0.3 Bugfix: In some case, CAN engine won't start (bad state on RB2)
; Bugfix: goto protection not working for some devices
; Improvement: renamed fosc to oscf for compatibility with some devices
; 2.0.2 Change: node ID configuration moved in settings.inc
; New feature: goto protection
; New feature: bl protection
; Change: size is 7 pages
; Bugfix: compatible with devices that has no eeprom (2450, 4450 and more)
; 2.0.1 New feature: adjustable non hello discard, HELLORETRIES setting
; Improvement: compatible with include files containing both TXSTA and TXSTA1 definitions
; Improvement: 5 or 7 (see section Init) more instructions free to use (CAN)
; 2.0.0 CAN support
; 1.0.2 Replaced old baudrate calculator
; 1.0.1 Erase is now made just before write to increase reliability
; 1.0.0 Separated boot timeout and receive timeout
; Added range check of times and brg
; 0.9.2 Changed bootloader size to 5 pages (to make room for more user init code)
; Added tx enable support
; 0.9.1 1 more instruction free to use
; Added watchdog clear
; Fixed baudrate error check
; Correct buffer size
; 0.9.0 Initial release
;------------------------------------------------------------------------------
;-----------------------------------------------------------------------------
; This file is part of ds30 Loader.
;
; ds30 Loader is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation.
;
; ds30 Loader is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with ds30 Loader. If not, see .
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Includes
;------------------------------------------------------------------------------
#include "settings.inc"
;------------------------------------------------------------------------------
; Defines
;------------------------------------------------------------------------------
#define VERENC 0
#define VERMAC 0
#define VERMAJ 3 ;firmware version major
#define VERMIN 0 ;firmware version minor
#define VERREV 0 ;firmware version revision
#define HELLO 0xC1
#define OK 'K' ;erase/write ok
#define CHECKSUMERR 'N' ;checksum error
#define VERFAIL 'V' ;verification failed
#define BLPROT 'P' ;bl protection tripped
#define UCMD 'U' ;unknown command
#define PWOK 0xFE
#if BLINIT < 2500
#define TMRBASE 10
#else
#define TMRBASE 30
#endif
#define DELBASE ( (TMRBASE * OSCF) / (3+(4000 * 255 * 6)) ) ;delay
#define BLSTART ( BLINIT / TMRBASE ) ;count for boot receive delay
#define BLDELAY ( BLTIME / TMRBASE ) ;count for receive delay
ifndef USE_BRG16
#define UBRG ( (((OSCF / BAUDRATE) / 8) - 1) / 2 ) ;baudrate
else
#define UBRG ( (((OSCF / BAUDRATE) / 2) - 1) / 2 ) ;baudrate
endif
#define PAGESIZER (PAGESIZEW/ROWSIZEW) ;pagesize [rows]
#define ROWSIZEB (ROWSIZEW*2) ;rowsize [bytes]
#define STARTADDR ( MAX_FLASH - BLPLP * PAGESIZER * ROWSIZEW * 2 ) ;bootloader placement
ifdef IS_PIC18F
#define ERASE_CODE b'10010100'
#define WRITE_CODE b'10000100'
else
#define ERASE_CODE b'00010100'
#define WRITE_CODE b'00000100'
endif
; Debug output
;messg STARTADDR_IS #v(STARTADDR)
;messg UBRG_IS #v(UBRG)
;messg delbaesis #v(DELBASE)
;messg blstartis #v(BLSTART)
;messg bldelayis #v(BLDELAY)
#ifdef USE_UART1
#define USE_UART 1
#endif
#ifdef USE_UART2
#define USE_UART 1
#endif
;------------------------------------------------------------------------------
; Range check
;------------------------------------------------------------------------------
if DELBASE > 255
error overflow in delay calculation
endif
if BLSTART > 255
error BLSTART_ is out of range
endif
if BLSTART == 0
error BLSTART might be out of range
endif
if BLDELAY > 255
error BLDELAY_ is out of range
endif
if BLDELAY == 0
error BLDELAY_ might be out of range
endif
;------------------------------------------------------------------------------
; Variables
;------------------------------------------------------------------------------
#define BUFFERSIZE (ROWSIZEB + 1 ) ;row + checksum
cblock 0x0
buffer : BUFFERSIZE
crc : 1 ;receive checksum
dcnt : 1 ;datacount
dcnt2 : 1 ;datacount
cnt1 : 1 ;receive timeout timer
cnt2 : 1 ;receive timeout timer
cnt3 : 1 ;receive timeout timer
cntHello : 1 ;
rowcnt : 1 ;row iterator
rowcnt2 : 1 ;
cmd : 1 ;command
doerase : 1 ;do erase before next write
ttblptru : 1
ttblptrh : 1
ttblptrl : 1
endc
;------------------------------------------------------------------------------
; Globals & externals
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Macros
;------------------------------------------------------------------------------
SendL macro sbyte
movlw sbyte
rcall Send
endm
;------------------------------------------------------------------------------
; Reset vector
;------------------------------------------------------------------------------
org 0x0000
goto blstart
;------------------------------------------------------------------------------
; GOTO user application
;------------------------------------------------------------------------------
org STARTADDR - 4 ;space to deposit goto to user application
loadusr nop
nop
;------------------------------------------------------------------------------
; Start of bootloader code
;------------------------------------------------------------------------------
org STARTADDR
blstart
;------------------------------------------------------------------------------
; Trouble shooting tools
;------------------------------------------------------------------------------
;bra dev_ftest
; Toggle pin, frequency on pin = PIC frequency / 16
if 0
bcf TRISx, TRISxx
tsfloop bsf LATx, LATxx
bcf LATx, LATxx
bra tsfloop
endif
;------------------------------------------------------------------------------
; User specific entry code go here
;------------------------------------------------------------------------------
;----------------------------------------------------------------------
; Make uart pins digital
;----------------------------------------------------------------------
ifdef ADCON1
;error Do you need to configura uart pins to be digital? If not, remove this line
endif
;movlw b'01100000' ;xxx disable
;movwf ADCON1 ;xxx analog on tx/rx
;Set Port C naar digitaal voor de 18F25K22 (kijk in de datasheet, dit is niet voor alle PIC's hetzelfde)
; banksel ANSELC ; you need this as ANSELC is at banked address.
; bcf ANSELC,7
;--------------------------------------------------------------------------------
; Set internal Oscilator frequenty
;--------------------------------------------------------------------------------
; Set internal oscillator to 8 MHz, (default for 18F25K20 = 1Mhz) xxx
movlw b'01100000' ;xxx
movwf OSCCON ;xxx
;18F25K20/22
; 01110000 = 16Mhz
; 01100000 = 8 Mhz
; 01010000 = 4 Mhz
; 01000000 = 2 Mhz
; 00110000 = 1 Mhz (default on reset)
; 00100000 = 500Khz
; 00010000 = 250Khz
; 00000000 = 31,25Khz
; ander type's starten vaak met 8Mhz op 01110000 en hebben zo over de hele range andere freqenties (zie datasheet)
;----------------------------------------------------------------------
; UART/CAN pps config
;----------------------------------------------------------------------
ifdef HAS_PPS
ifdef USE_UART2
error You need to configure PPS
; This template maps U2Rx to RP4
bcf RPINR16, RX2DT2R0 ;xxx
bcf RPINR16, RX2DT2R1 ;xxx
bsf RPINR16, RX2DT2R2 ;xxx
bcf RPINR16, RX2DT2R3 ;xxx
bcf RPINR16, RX2DT2R4 ;xxx
; This template maps RP3 to U2Tx
bsf RPOR3, RP3R0 ;xxx
bcf RPOR3, RP3R1 ;xxx
bsf RPOR3, RP3R2 ;xxx
bcf RPOR3, RP3R3 ;xxx
bcf RPOR3, RP3R4 ;xxx
endif
endif
;------------------------------------------------------------------------------
; Init
;------------------------------------------------------------------------------
clrf doerase
rcall CommInit
;----------------------------------------------------------------------
; Wait for computer
;----------------------------------------------------------------------
clrf cntHello
rhello movlw BLSTART
rcall RcvIni
sublw HELLO
bz rhellook
; Not hello received
incf cntHello
movf cntHello, w
sublw HELLOTRIES
bz exit
bra rhello
rhellook
;----------------------------------------------------------------------
; Send device id and firmware version
;----------------------------------------------------------------------
sendid SendL ( DEVICEID & 0xff )
SendL ( ((DEVICEID&0x100)>>1) + VERMAC + VERENC + VERMAJ )
SendL ( ((DEVICEID&0x200)>>2) + (VERMIN<<4) + VERREV )
;----------------------------------------------------------------------
; Main loop
;----------------------------------------------------------------------
Main SendL OK ;last command was successfull, waiting for next
mainl clrf crc
;----------------------------------------------------------------------
; Receive address
;----------------------------------------------------------------------
;Upper byte
rcall Receive
movwf TBLPTRU
; High byte
rcall Receive
movwf TBLPTRH
#ifdef BIGEE
movwf EEADRH ;for eeprom
endif
; Low byte
rcall Receive
movwf TBLPTRL
#ifdef EEADR
movwf EEADR ;for eeprom
endif
;----------------------------------------------------------------------
; Receive command
;----------------------------------------------------------------------
rcall Receive
movwf cmd
;----------------------------------------------------------------------
; Receive nr of data bytes that will follow
;----------------------------------------------------------------------
rcall Receive
movwf dcnt
movwf dcnt2
;----------------------------------------------------------------------
; Receive data
;----------------------------------------------------------------------
lfsr FSR0, buffer ;load buffer pointer to fsr0
rcvoct rcall Receive
movwf POSTINC0
decfsz dcnt
bra rcvoct
;----------------------------------------------------------------------
; Check checksum
;----------------------------------------------------------------------
tstfsz crc
bra crcfail
chksumok
;----------------------------------------------------------------------
; 0x00 goto protection
;----------------------------------------------------------------------
ifdef PROT_GOTO
; Only for write row command
btfss cmd, 1
bra protgotook
; Check for row 0
tstfsz TBLPTRU
bra protgotook
tstfsz TBLPTRH
bra protgotook
tstfsz TBLPTRL
bra protgotook
; Init buffer pointer
lfsr FSR0, buffer ;load buffer pointer to fsr0
; 1st word low byte = low address byte
movlw ((STARTADDR>>1)&0xff)
movwf POSTINC0
; 1st word high byte = goto instruction
movlw 0xef
movwf POSTINC0
; 2nd word low byte = upper address byte
movlw (((STARTADDR>>1)&0xff00)>>8)
movwf POSTINC0
; 2nd word high byte = uppder address nibble + goto instruction
movlw (0xf0 + (((STARTADDR>>1)&0xf0000)>>16))
movwf POSTINC0
protgotook
endif
;----------------------------------------------------------------------
; Init buffer pointer
;----------------------------------------------------------------------
lfsr FSR0, buffer ;load buffer pointer to fsr0
;----------------------------------------------------------------------
; Check command
;----------------------------------------------------------------------
; Erase page, set do erase status flag
btfss cmd, 0
bra cmdrow
setf doerase
bra Main
; Write row
cmdrow btfsc cmd, 1
bra blprot
; Write eeprom word
ifdef EEDATA
btfsc cmd, 2
bra eeprom
endif
; Write config
btfsc cmd, 3
bra cfg
; Else, unknown command
SendL UCMD
bra mainl
;------------------------------------------------------------------------------
; Exit, placed here so it can be branched to from all code, max +-127
;------------------------------------------------------------------------------
exit
rcall CommExit
bra loadusr
;----------------------------------------------------------------------
; Bootloader protection
;----------------------------------------------------------------------
blprot nop
ifdef PROT_BL
if PAGESIZEW == 16
#define ROTROUNDS 5
endif
if PAGESIZEW == 32 ;most PIC18F
#define ROTROUNDS 6
endif
if PAGESIZEW == 64 ;some PIC18F
#define ROTROUNDS 7
endif
if PAGESIZEW == 128
#define ROTROUNDS 8
endif
if PAGESIZEW == 256
#define ROTROUNDS 9
endif
if PAGESIZEW == 512 ;PIC18FJ
#define ROTROUNDS 10
endif
; Make a copy of address
movff TBLPTRU, ttblptru
movff TBLPTRH, ttblptrh
movff TBLPTRL, ttblptrl
; Calculate page number of received address
movlw ROTROUNDS ;2^6=64=pagesize[bytes]
#undefine ROTROUNDS
movwf cnt1
bcf STATUS, C ;clear carry bit
calcpage rrcf ttblptru, 1
rrcf ttblptrh, 1
rrcf ttblptrl, 1
decfsz cnt1
bra calcpage
; Received page high < bl start page = OK
movlw ((STARTADDR/(PAGESIZEW*2))>>8)
subwf ttblptrh, 0
bn blprotok
; Received page = bl start page
movlw ((STARTADDR/(PAGESIZEW*2))>>8)
subwf ttblptrh, 0
bnz chkgt
; Received page low < bl start page low = OK
movlw ((STARTADDR/(PAGESIZEW*2))&0xff)
subwf ttblptrl, 0
bn blprotok
; Received page high > bl end page = OK
chkgt movlw (((STARTADDR/(PAGESIZEW*2))+BLSIZEP-1)>>8)
subwf ttblptrh, 0
bz chkgt2
bn chkgt2
bra blprotok
; Received page = bl end page
chkgt2 movlw (((STARTADDR/(PAGESIZEW*2))+BLSIZEP-1)>>8)
subwf ttblptrh, 0
bnz proterr
; Received page low > bl end page low = OK
movlw (((STARTADDR/(PAGESIZEW*2))+BLSIZEP-1)&0xff)
subwf ttblptrl, 0
bz proterr
bn proterr
bra blprotok
; Protection tripped
proterr SendL BLPROT
bra mainl
endif
;----------------------------------------------------------------------
; Erase page
;----------------------------------------------------------------------
blprotok
erase btfss doerase, 0
bra wrloop
movlw ERASE_CODE ;setup erase
rcall Write
clrf doerase
;----------------------------------------------------------------------
; Write row
;----------------------------------------------------------------------
wrloop movlw ROWSIZEB
movwf rowcnt
movwf rowcnt2
; Load latches
wrbyte movff POSTINC0, TABLAT
tblwt *+
decfsz rowcnt
bra wrbyte
; Write
tblrd *- ;point back into row
movlw WRITE_CODE
rcall Write
;----------------------------------------------------------------------
; Verify row
;----------------------------------------------------------------------
lfsr FSR0, (buffer+(ROWSIZEB-1)) ;load buffer pointer to fsr0
; Read
verbyte tblrd *-
movf POSTDEC0, w
; Compare
cpfseq TABLAT
bra verfail
; Loop?
decfsz rowcnt2
bra verbyte
; Verify succesfull
bra Main
;----------------------------------------------------------------------
; Erase, write & verify eeprom word
;----------------------------------------------------------------------
ifdef EEADR
; Load latch
eeprom movff INDF0, EEDATA
; Write
movlw b'00000100'
rcall Write
; Verify, read byte
movlw b'00000001'
bsf EECON1, RD
movf INDF0, w
; Compare
cpfseq EEDATA
bra verfail
; Verify succesfull
bra Main
endif
;----------------------------------------------------------------------
; Write config byte
;----------------------------------------------------------------------
; Load latch
cfg movff INDF0, TABLAT
tblwt *
; Write
movlw b'11000100'
rcall Write
; Write finished
bra Main
;----------------------------------------------------------------------
; Verify fail
;----------------------------------------------------------------------
verfail SendL VERFAIL
bra mainl
;----------------------------------------------------------------------
; Checksum error
;----------------------------------------------------------------------
crcfail SendL CHECKSUMERR
bra mainl
;------------------------------------------------------------------------------
; Write()
;------------------------------------------------------------------------------
Write movwf EECON1
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1, WR
; Wait for write to finish, only needed for eeprom
waitwre btfsc EECON1, WR
bra waitwre
bcf EECON1,WREN ;disable writes
return
;------------------------------------------------------------------------------
; Functions
;------------------------------------------------------------------------------
ifdef USE_UART
#include "uart.inc"
endif
;------------------------------------------------------------------------------
; End of code
;
; After reset
; Do not expect the memory to be zero,
; Do not expect registers to be initialised as described in datasheet.
;------------------------------------------------------------------------------
end
;------------------------------------------------------------------------------
; User specific entry code go here
;------------------------------------------------------------------------------
;----------------------------------------------------------------------
; Make uart pins digital
;----------------------------------------------------------------------
ifdef ADCON1
;error Do you need to configura uart pins to be digital? If not, remove this line
endif
;movlw b'01100000' ;xxx disable
;movwf ADCON1 ;xxx analog on tx/rx
;Set Port C naar digitaal voor de 18F25K22 (kijk in de datasheet, banksel is niet voor alle PIC's hetzelfde)
banksel ANSELC ; you need this as ANSELC is at banked address.
bcf ANSELC,7
;--------------------------------------------------------------------------------
; Set internal Oscilator frequenty
Bij dit type is de communicatie poort C7 (RX) in eerste instantie analoog en moeten die in het ANSELC (analoog select poort C) eerst op digitaal gezet worden.