📄 canio.asm
字号:
;*****************************************************************************
;*
;* Microchip CAN Bootloader
;*
;*****************************************************************************
;* FileName: CANIO.asm
;* Dependencies:
;* Processor: PIC18F with CAN
;* Assembler: MPASMWIN 03.10.04 or higher
;* Linker: MPLINK 03.10.04 or higher
;* Company: Microchip Technology Incorporated
;*
;* Software License Agreement
;*
;* The software supplied herewith by Microchip Technology Incorporated
;* (the "Company") is intended and supplied to you, the Company's
;* customer, for use solely and exclusively with products manufactured
;* by the Company.
;*
;* The software is owned by the Company and/or its supplier, and is
;* protected under applicable copyright laws. All rights are reserved.
;* Any use in violation of the foregoing restrictions may subject the
;* user to criminal sanctions under applicable laws, as well as to
;* civil liability for the breach of the terms and conditions of this
;* license.
;*
;* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
;* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
;* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
;* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
;* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;*
;*
;* Basic Operation:
;* The following is a CAN bootloader designed for PIC18F microcontrollers
;* with built-in CAN such as the PIC18F458. The bootloader is designed to
;* be simple, small, flexible, and portable.
;*
;* The bootloader can compiled to one of two major modes of operation:
;*
;* PG Mode: In this mode the bootloader allows bi-directional communication
;* with the source. Thus the bootloading source can query the
;* target and verify the data being written.
;*
;* P Mode: In this mode the bootloader allows only single direction
;* communication, i.e. source -> target. In this mode programming
;* verification is provided by performing self verification and
;* checksum of all written data (except for control data).
;*
;* The bootloader is essencially a register controlled system. The control
;* registers hold information that dictates how the bootloader functions.
;* Such information includes a generic pointer to memory, control bits to
;* assist special write and erase operations, and special command registers
;* to allow verification and release of control to the main application.
;*
;* After setting up the control registers, data can be sent to be written
;* to or a request can be sent to read from the selected memory defined by
;* the address. Depending on control settings the address may or may not
;* automatically increment to the next address.
;*
;* Commands:
;* Put commands received from source (Master --> Slave)
;* The count (DLC) can vary.
;* XXXXXXXXXXX 0 0 8 XXXXXXXX XXXXXX00 ADDRL ADDRH ADDRU RESVD CTLBT SPCMD CPDTL CPDTH
;* XXXXXXXXXXX 0 0 8 XXXXXXXX XXXXXX01 DATA0 DATA1 DATA2 DATA3 DATA4 DATA5 DATA6 DATA7
;*
;* The following responce commands are only used for PG mode.
;* Get commands received from source (Master --> Slave)
;* Uses control registers to get data. Eight bytes are always assumed.
;* XXXXXXXXXXX 0 0 0 XXXXXXXX XXXXXX10 _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__
;* XXXXXXXXXXX 0 0 0 XXXXXXXX XXXXXX11 _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__
;*
;* Put commands sent upon receiving Get command (Slave --> Master)
;* YYYYYYYYYYY 0 0 8 YYYYYYYY YYYYYY00 ADDRL ADDRH ADDRU RESVD STATS RESVD RESVD RESVD
;* YYYYYYYYYYY 0 0 8 YYYYYYYY YYYYYY01 DATA0 DATA1 DATA2 DATA3 DATA4 DATA5 DATA6 DATA7
;*
;* Put commands sent upon receiving Put command (if enabled) (Slave --> Master)
;* This is the acknowledge after a put.
;* YYYYYYYYYYY 0 0 0 YYYYYYYY YYYYYY00 _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__
;* YYYYYYYYYYY 0 0 0 YYYYYYYY YYYYYY01 _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__ _NA__
;*
;* ADDRL - Bits 0 to 7 of the memory pointer.
;* ADDRH - Bits 8 - 15 of the memory pointer.
;* ADDRU - Bits 16 - 23 of the memory pointer.
;* RESVD - Reserved for future use.
;* CTLBT - Control bits.
;* SPCMD - Special command.
;* CPDTL - Bits 0 - 7 of special command data.
;* CPDTH - Bits 8 - 15 of special command data.
;* DATAX - General data.
;*
;* Control bits:
;* MODE_WRT_UNLCK - Set this to allow write and erase operations to memory.
;* MODE_ERASE_ONLY - Set this to only erase Program Memory on a put command. Must
;* be on 64 byte boundary.
;* MODE_AUTO_ERASE - Set this to automatically erase Program Memory while writing data.
;* MODE_AUTO_INC - Set this to automatically increment the pointer after writing.
;* MODE_ACK - Set this to generate an acknowledge after a 'put' (PG Mode only)
;*
;* Special Commands:
;* CMD_NOP 0x00 Do nothing
;* CMD_RESET 0x01 Issue a soft reset
;* CMD_RST_CHKSM 0x02 Reset the checksum counter and verify
;* CMD_CHK_RUN 0x03 Add checksum to special data, if verify and zero checksum
;* then clear the last location of EEDATA.
;* Memory Organization:
;* |-------------------------------|
;* | | 0x000000 (Do not write here!)
;* | Boot Area |
;* | |
;* |-------------------------------|
;* | |
;* | |
;* | |
;* | |
;* | Prog Mem |
;* | |
;* | |
;* | |
;* | | 0x1FFFFF
;* |-------------------------------|
;* | User ID | 0x200000
;* |-------------------------------|
;* |:::::::::::::::::::::::::::::::|
;* |:::::::::::::::::::::::::::::::|
;* |-------------------------------|
;* | Config | 0x300000
;* |-------------------------------|
;* |:::::::::::::::::::::::::::::::|
;* |:::::::::::::::::::::::::::::::|
;* |-------------------------------|
;* | Device ID | 0x3FFFFE
;* |-------------------------------|
;* |:::::::::::::::::::::::::::::::|
;* |:::::::::::::::::::::::::::::::|
;* |:::::::::::::::::::::::::::::::|
;* |:::::::::::::::::::::::::::::::|
;* |-------------------------------|
;* | | 0xF00000
;* | EEDATA |
;* | (remapped) |
;* | | (Last byte used as boot flag)
;* |-------------------------------|
;*
;*
;* Author Date Comment
;*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;* Ross Fosler 11/26/02 First full revision
;*
;*****************************************************************************/
; *****************************************************************************
#include p18cxxx.inc
#include canio.def
; *****************************************************************************
; *****************************************************************************
#ifndef EEADRH
#define EEADRH EEADR+1
#endif
#define TRUE 1
#define FALSE 0
#define WREG1 PRODH ; Alternate working register
#define WREG2 PRODL
#define MODE_WRT_UNLCK _bootCtlBits,0 ; Unlock write and erase
#define MODE_ERASE_ONLY _bootCtlBits,1 ; Erase without write
#define MODE_AUTO_ERASE _bootCtlBits,2 ; Enable auto erase before write
#define MODE_AUTO_INC _bootCtlBits,3 ; Enable auto inc the address
#define MODE_ACK _bootCtlBits,4 ; Acknowledge mode
#define ERR_VERIFY _bootErrStat,0 ; Failed to verify
#define CMD_NOP 0x00
#define CMD_RESET 0x01
#define CMD_RST_CHKSM 0x02
#define CMD_CHK_RUN 0x03
; *****************************************************************************
; *****************************************************************************
_MEM_IO_DATA UDATA_ACS 0x00
; *****************************************************************************
_bootCtlMem
_bootAddrL RES 1 ; Address info
_bootAddrH RES 1
_bootAddrU RES 1
_unused0 RES 1 ; (Reserved)
_bootCtlBits RES 1 ; Boot Mode Control bits
_bootSpcCmd RES 1 ; Special boot commands
_bootChkL RES 1 ; Special boot command data
_bootChkH RES 1
_bootCount RES 1
_bootChksmL RES 1 ; 16 bit checksum
_bootChksmH RES 1
_bootErrStat RES 1 ; Error Status flags
; *****************************************************************************
; *****************************************************************************
_REMAP_STARTUP CODE RESET_VECT
; *****************************************************************************
ResetRemapped
; *****************************************************************************
_REMAP_INTV_H CODE HIGH_INT_VECT
; *****************************************************************************
IntVectHighRemapped
; *****************************************************************************
_REMAP_INTV_L CODE LOW_INT_VECT
; *****************************************************************************
IntVectLowRemapped
; *****************************************************************************
_STARTUP CODE 0x00
; *****************************************************************************
bra _CANInit
bra _StartWrite
; *****************************************************************************
_INTV_H CODE 0x08
; *****************************************************************************
#ifdef NEAR_JUMP
bra IntVectHighRemapped
#else
goto IntVectHighRemapped
#endif
; *****************************************************************************
_INTV_L CODE 0x18
; *****************************************************************************
#ifdef NEAR_JUMP
bra IntVectLowRemapped
#else
goto IntVectLowRemapped
#endif
; *****************************************************************************
; *****************************************************************************
_CAN_IO_MODULE CODE
; *****************************************************************************
; Function: VIOD _StartWrite(WREG _eecon_data)
;
; PreCondition: Nothing
;
; Input: _eecon_data
;
;
; Output: Nothing. Self write timing started.
;
; Side
; Effects: EECON1 is corrupted.
; WREG is corrupted.
;
; Stack
; Requirements: 1 level.
;
; Overview: Unlock and start the write or erase sequence to protected
; memory. Function will wait until write is finished.
; *****************************************************************************
_StartWrite:
movwf EECON1
btfss MODE_WRT_UNLCK ; Stop if write locked
return
movlw 0x55 ; Unlock
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1, WR ; Start the write
nop
btfsc EECON1, WR ; Wait (depends on mem type)
bra $ - 2
return
; *****************************************************************************
; *****************************************************************************
; Function: _bootChksm _UpdateChksum(WREG _bootChksmL)
;
; PreCondition: Nothing
;
; Input: _bootChksmL
;
;
; Output: _bootChksm. This is a static 16 bit value stored in the
; Access Bank.
;
; Side
; Effects: STATUS register is corrupted.
;
; Stack
; Requirements: 1 level.
;
; Overview: This function adds a byte to the current 16 bit checksum
; count. WREG should contain the byte before being called.
;
; The _bootChksm value is considered a part of the special
; register set for bootloading. Thus it is not visible.
;***************************************************************************
_UpdateChksum:
addwf _bootChksmL, F ; Keep a checksum
btfsc STATUS, C
incf _bootChksmH, F
return
; *****************************************************************************
; *****************************************************************************
; Function: VOID _CANInit(CAN, BOOT)
;
; PreCondition: Enter only after a reset has occured.
;
; Input: CAN control information, bootloader control information
;
; Output: None.
;
; Side
; Effects: N/A. Only run imediately after reset.
;
; Stack
; Requirements: N/A
;
; Overview: This routine is technically not a function since it will not
; return when called. It has been written in a linear form to
; save space. Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;
; This routine tests the boot flags to determine if boot mode is
; desired or normal operation is desired. If boot mode then the
; routine initializes the CAN module defined by user input. It
; also resets some registers associated to bootloading.
; *****************************************************************************
_CANInit:
clrf EECON1
setf EEADR ; Point to last location of EEDATA
setf EEADRH
bsf EECON1, RD ; Read the control code
incfsz EEDATA, W
#ifdef NEAR_JUMP
bra ResetRemapped ; If not 0xFF then normal reset
#else
goto ResetRemapped
#endif
clrf _bootSpcCmd ; Reset the special command register
movlw 0x1C ; Reset the boot control bits
movwf _bootCtlBits
movlb d'15' ; Set Bank 15
bcf TRISB, CANTX ; Set the TX pin to output
movlw CAN_RXF0SIDH ; Set filter 0
movwf RXF0SIDH
movlw CAN_RXF0SIDL
movwf RXF0SIDL
comf WREG ; Prevent filter 1 from causing a
movwf RXF1SIDL ; receive event
movlw CAN_RXF0EIDH
movwf RXF0EIDH
movlw CAN_RXF0EIDL
movwf RXF0EIDL
movlw CAN_RXM0SIDH ; Set mask
movwf RXM0SIDH
movlw CAN_RXM0SIDL
movwf RXM0SIDL
movlw CAN_RXM0EIDH
movwf RXM0EIDH
movlw CAN_RXM0EIDL
movwf RXM0EIDL
movlw CAN_BRGCON1 ; Set bit rate
movwf BRGCON1
movlw CAN_BRGCON2
movwf BRGCON2
movlw CAN_BRGCON3
movwf BRGCON3
movlw CAN_CIOCON ; Set IO
movwf CIOCON
clrf CANCON ; Enter Normal mode
; *****************************************************************************
; *****************************************************************************
; This routine is essencially a polling loop that waits for a
; receive event from RXB0 of the CAN module. When data is
; received, FSR0 is set to point to the TX or RX buffer depending
; upon whether the request was a 'put' or a 'get'.
; *****************************************************************************
_CANMain:
bcf RXB0CON, RXFUL ; Clear the receive flag
btfss RXB0CON, RXFUL ; Wait for a message
bra $ - 2
clrwdt
#ifdef ALLOW_GET_CMD
btfss CAN_PG_BIT ; Put or get data?
bra _CANMainJp1
lfsr 0, TXB0D0 ; Set pointer to the transmit buffer
movlw 0x08
movwf _bootCount ; Setup the count to eight
movwf WREG1
bra _CANMainJp2
#endif
_CANMainJp1
lfsr 0, RXB0D0 ; Set pointer to the receive buffer
movf RXB0DLC, W
andlw 0x0F
movwf _bootCount ; Store the count
movwf WREG1
bz _CANMain ; Go back if no data specified for a put
_CANMainJp2
; *****************************************************************************
; *****************************************************************************
; Function: VOID _ReadWriteMemory()
;
; PreCondition: Enter only after _CANMain().
;
; Input: None.
;
; Output: None.
;
; Side
; Effects: N/A.
;
; Stack
; Requirements: N/A
;
; Overview: This routine is technically not a function since it will not
; return when called. It has been written in a linear form to
; save space. Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;
; This is the memory I/O engine. A total of eight data
; bytes are received and decoded. In addition two control
; bits are received, put/get and control/data.
;
; A pointer to the buffer is passed via FSR0 for reading or writing.
;
; The control register set contains a pointer, some control bits
; and special command registers.
;
; Control
; <PG><CD><ADDRL><ADDRH><ADDRU><_RES_><CTLBT><SPCMD><CPDTL><CPDTH>
;
; Data
; <PG><CD><DATA0><DATA1><DATA2><DATA3><DATA4><DATA5><DATA6><DATA7>
;
; PG bit Put = 0, Get = 1
; CD bit Control = 0, Data = 1
; *****************************************************************************
_ReadWriteMemory:
btfsc CAN_CD_BIT ; Write/read data or control registers
bra _DataReg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -