M
Author:
TB025
ACCESSING MEMORY
The read and write operations are controlled by a set of
Special Function Registers (SFRs). There are six
SFRs required to access the FLASH program memory:
•
•
•
•
•
•
EECON1
EECON2
EEDATA
EEDATH
EEADR
EEADRH
Downloading HEX Files to PIC16F87X PICmicro
®
Microcontrollers
Rodger Richey
Microchip Technology Inc.
INTRODUCTION
The release of the PIC16F87X devices introduces the
first mid-range family of devices from Microchip Tech-
nology that has the capability to read and write to inter-
nal program memory. This family has FLASH-based
program memory, SRAM data memory and EEPROM
data memory. The FLASH program memory allows for
a truly reprogrammable system. Table 1 shows the fea-
tures of the PIC16F87X family of devices.
The registers
EEADRH:EEADR
holds the 12-bit address
required to access a location in the 8K words of pro-
gram memory. The registers
EEDATH:EEDATA
are used
to hold the data values. When reading program mem-
ory, the
EEPGD
bit
(EECON1<7>)
must be set to indicate
to the microcontroller that the operation is going to be
on program memory. If the bit is cleared, the operation
will be performed on data memory at the address
pointed to by
EEADR
. The
EEDATA
register will hold the
data. The
EECON1
register also has bits for write enable
and to initiate the read or write operation. There is also
a bit to indicate a write error has occurred, possibly due
to a reset condition happening while a write operation
is in progress. Figure 1 shows the register map for
EECON1
.
The
EECON2
register is not a physical register. Reading
it will result in all '0's. This register is used exclusively
in the EEPROM and FLASH write sequences.
Listing 1
shows the code snippet to initiate a write operation on
the PIC16F87X devices.
TABLE 1
PIC16F87X FAMILY FEATURES
Key Features
PIC16F873
DC - 20 MHz
POR, BOR
4K
192
128
13
Ports A,B,C
3
2
MSSP, USART
—
5 input channels
PIC16F874
DC - 20 MHz
POR, BOR
4K
192
128
14
Ports A,B,C,D,E
3
2
MSSP, USART
PSP
8 input channels
PIC16F876
DC - 20 MHz
POR, BOR
8K
368
256
13
Ports A,B,C
3
2
MSSP, USART
—
5 input channels
PIC16F877
DC - 20 MHz
POR, BOR
8K
368
256
14
Ports A,B,C,D,E
3
2
MSSP, USART
PSP
8 input channels
Operating Frequency
Resets
Flash Prog Memory (14-bit words)
Data Memory (bytes)
EEPROM Data Memory
Interrupts
I/O Ports
Timers
Capture/Compare/PWM modules
Serial Communications
Parallel Communications
10-bit Analog-to-Digital Module
©
1998 Microchip Technology Inc.
DS91025A-page 1
TB025
FIGURE 1:
R/W-x
U-0
EEPGD —
bit7
EECON1 REGISTER
U-0
—
U-0
—
R/W-x
R/W-0
WRERR WREN
R/S-0
WR
R/S-0
RD
bit0
R= Readable bit
W= Writable bit
S= Settable bit
U= Unimplemented bit,
read as ‘0’
- n= Value at POR reset
bit 7:
EEPGD
: Program / Data EEPROM Select bit
1 = Accesses Program memory
0 = Accesses data memory
Note: This bit cannot be changed while a write operation is in progress.
WRERR
: EEPROM Error Flag bit
1 = A write operation is prematurely terminated
(any MCLR reset or any WDT reset during normal operation)
0 = The write operation completed
WREN
: EEPROM Write Enable bit
1 = Allows write cycles
0 = Inhibits write to the EEPROM
WR
: Write Control bit
1 = initiates a write cycle.
The bit is cleared by hardware once write is complete.
The WR bit can only be set (not cleared) in software.
0 = Write cycle to the EEPROM is complete
RD
: Read Control bit
1 = Initiates an EEPROM read (read takes one cycle)
RD is cleared in hardware. The RD bit can only be set (not cleared) in software.
0 = Does not initiate an EEPROM read
on the line. Divide this number by two to get the
number of words per line.
AAAA
- is a four digit hexadecimal address repre-
senting the starting address of the data record.
Format is high byte first followed by low byte. The
address is doubled because this format only sup-
ports 8-bits (to find the real PICmicro address,
simply divide the value
AAAA
by 2).
TT
- is a two digit record type that will be '00' for
data records, '01' for end of file records and '04'
for extended address record (INHX32 only).
HHHH
- is a four digit hexadecimal data word. For-
mat is low byte followed by high byte. There will
be
BB
/2 data words following
TT.
CC
- is a two digit hexadecimal checksum that is
the two's complement of the sum of all the pre-
ceding bytes in the line record.
bit 6:4:
Unimplemented:
Read as '0'
bit 3:
bit 2:
bit 1:
bit 0:
HEX FILE FORMAT
The data to be programmed into program memory will
be read into the microcontroller using one of its stan-
dard interface modules: SPI, I
2
C™, USART, or PSP.
Probably the simplest format to send the data to the
microcontroller is in the standard HEX format used by
the Microchip development tools. The formats sup-
ported are the Intel HEX Format (INHX8M), Intel Split
HEX Format (INHX8S), and the Intel HEX 32 Format
(INHX32). The most commonly used formats are the
INHX8M and INHX32 and therefore are the only for-
mats discussed in this document. Please refer to
Appendix A in the MPASM User's Guide (DS33014) for
more information about HEX file formats. The differ-
ence between INHX8M and INHX32 is that INHX32
supports 32-bit addresses using a linear address
record. The basic format of the hex file is the same
between both formats as shown below:
:BBAAAATTHHHH...HHHHCC
Each data record begins with a 9 character prefix and
always ends with a 2 character checksum. All records
begin with a '
:
' regardless of the format. The individual
elements are described below.
•
BB
- is a two digit hexadecimal byte count repre-
senting the number of data bytes that will appear
DS91025A-page 2
•
•
•
•
Since the PIC16F87X devices only have a maximum of
8K words, the linear address record '04' is ignored by
the routine. The HEX file is composed of ASCII char-
acters 0 thorough 9 and A to F and the end of each line
has a carriage return and linefeed. The downloader
code in the PICmicro microcontrollers must convert the
ASCII characters to binary numbers to be used for pro-
gramming.
©
1998 Microchip Technology Inc.
TB025
PICmicro Code
The sample downloader code does not specifically use
one of the interface modules on the PIC16F87X device.
Instead, a routine called
GetByte
retrieves a single
character from the HEX file over the desired interface.
It is up to the engineer to write this routine around the
desired interface. Another routine
GetHEX8
calls
Get-
Byte
twice to form a two digit hexadecimal number.
One issue that arises is how many times to reprogram
a location that does not program correctly. The sample
code provided simply exits the downloader routine and
stores a value of 0xFF in the
WREG
if a program memory
location does not properly program on the first attempt.
The engineer may optionally add code to loop several
times if this event occurs.
Still another issue that is not specifically addressed in
the sample code is to prevent the downloader from
overwriting its own program memory address locations.
The designer must add an address check to prevent
this situation from happening.
Finally, the designer must account for situations where
the download of new code into the microcontroller is
interrupted by an external event such as power failure
or reset. The system must be able to recover from such
an event. This is not a trivial task, is very system
dependent, and is therefore left up to the designer to
provide the safeguards and recovery mechanisms.
Another error that could happen is a line checksum
error. If the calculated line checksum does not match
the line checksum from the HEX file, a value of 1 is
returned in
WREG
. The part of the routine that calls the
downloader should check for the errors 0xFF (could not
program a memory location) and 1. If program memory
is programmed correctly and no errors have been
encountered, the downloader routine returns a 0 in
WREG
to indicate success to the calling routine. Figure
2 shows the flowchart for the downloader routines.
Listing 2
shows the complete listing for the downloader
code.
The routine
ASCII2HEX
converts the input character to
a binary number. The routine does not provide any out
of range error checking for incoming characters. Since
the only valid characters in a HEX file are the colon (:),
the numbers 0 through 9 and the letters A through F,
the routine can be highly optimized. It first subtracts 48
from the character value. For the ASCII numbers 0
through 9, this results in a value from 0 to 9. If the char-
acter is A through F, the result is a number greater than
15. The routine checks to see if the upper nibble of the
result is 0. If not 0, then the original value was A
through F and the routine now subtracts an additional
43 from the character resulting in the binary values 10
through 15. The colon is not accounted for in this rou-
tine because the main part of the downloader code
uses it as a line sync.
LISTING 1:
bsfSTATUS,RP1
bcfSTATUS,RP0
movfAddrH,W
movwfEEADRH
movfAddrL,W
movwfEEADR
bsfSTATUS,RP0
bsfEECON1,EEPGD
bsfEECON1,RD
bcfSTATUS,RP0
nop
movfEEDATA,W
…
movfEEDATH,W
…
FLASH WRITE SEQUENCE
; Bank2
; Load address into
; EEADRH:EEADR
;
;
;
;
Bank3
Set for Prog Mem
read operation
Bank2
; Data is read
; user can now
; access memory
©
1998 Microchip Technology Inc.
DS91025A-page 3
TB025
LISTING 2:
HEX DOWNLOAD CODE WRITTEN FOR MPASM
list p=16f877
#include "c:\progra~1\mplab\p16f877.inc"
DownloadCode
banksel
DCStart
call
movlw
subwf
btfss
goto
call
movwf
movwf
bcf
rrf
call
movwf
addwf
call
movwf
addwf
call
movwf
addwf
DataRec
movf
btfss
goto
DRLoop
movf
btfsc
goto
call
movwf
addwf
call
movwf
addwf
WriteDataSequence
banksel
movf
movwf
movf
movwf
movf
movwf
movf
movwf
banksel
bsf
bsf
bcf
movlw
movwf
movlw
movwf
bsf
nop
;Uses USART to receive data from PC
RCREG
GetByte
':'
RCREG,W
STATUS,Z
DCStart
GetHex8
ByteCount
LineChecksum
STATUS,C
ByteCount,F
GetHex8
AddrH
LineChecksum,F
GetHex8
AddrL
LineChecksum,F
GetHex8
RecType
LineChecksum,F
;Wait for colon
;Read byte count
;Store in register
;Store in line checksum
;Divide byte counter by 2 to get words
;Read high byte of 16-bit address
;Add high byte to line checksum
;Read low byte of 16-bit address
;Add low byte to line checksum
;Read record type
;Add to line checksum
;Data reception
;Check for data record (0h)
;Otherwise check for EOF
;Check for bytecount = 0
;If zero, goto checksum validation
;Read lower byte of data (2 characters)
;Add received data to checksum
;Read upper byte of data (2 characters)
;Add received data to checksum
RecType,F
STATUS,Z
EndOfFileRec
ByteCount,F
STATUS,Z
DRCkChecksum
GetHex8
HexDataL
LineChecksum,F
GetHex8
HexDataH
LineChecksum,F
;Write sequence to internal prog. mem FLASH
EEADRH
AddrH,W
EEADRH
AddrL,W
EEADR
HexDataH,W
EEDATH
HexDataL,W
EEDATA
EECON1
EECON1,EEPGD
EECON1,WREN
INTCON,GIE
0x55
EECON2
0xaa
EECON2
EECON1,WR
;Write address to EEADRH:EEADR registers
;Write data to EEDATH:EEDATA registers
;Write sequence
;Set EEPGD to indicate program memory
;Enable writes to memory
;Make sure interrupts are disabled
;Required write sequence
;Start internal write cycle
DS91025A-page 4
©
1998 Microchip Technology Inc.
TB025
nop
bcf
banksel
bsf
bsf
bcf
nop
movf
subwf
btfss
retlw
movf
subwf
btfss
retlw
incf
btfsc
incf
decf
goto
DRCkChecksum
call
addwf
btfss
retlw
goto
EndOfFileRec
decf
btfss
goto
call
addwf
btfss
retlw
retlw
EECON1,WREN
EECON1
EECON1,EEPGD
EECON1,RD
STATUS,RP0
EEDATH,W
HexDataH,W
STATUS,Z
0xff
EEDATA,W
HexDataL,W
STATUS,Z
0xff
AddrL,F
STATUS,Z
AddrH,F
ByteCount,F
DRLoop
;Disable writes
;Read sequence
;Set EEPGD to indicate program memory
;Enable reads from memory
;Compare memory value to HexDataH:HexDataL
;If upper byte not equal, return FFh
; to indicate programming failure
;If lower byte not equal, return FFh
; to indicate programming failure
;Increment address for next iteration
;Decrement byte count
;Go back to check for ByteCount = 0
;Checksum verification
;Read in checksum
;Add to calculated checksum
;Result should be 0
; If not return 1 to indicate checksum fail
;Do it again
;End of File record (01h)
;If EOF record, decrement should = 0
;Not valid record type, wait for next :
;Read in checksum
;Add to calculated checksum
;Result should be 0
; If not return 1 to indicate checksum fail
;Otherwise return 0 to indicate success
GetHex8
LineChecksum,W
STATUS,Z
1
DCStart
RecType,W
STATUS,Z
DCStart
GetHex8
LineChecksum,W
STATUS,Z
1
0
GetByte
; Insert your code here to retrieve a byte of data from
; the desired interface. In this case it is the USART on F877.
;clear CTS
;
banksel
PIR1
;GH4Waitbtfss
PIR1,RCIF
;
goto
GH4Wait
;set CTS
nop
banksel
RCREG
movf
RCREG,W
return
GetHex8
call
call
movwf
swapf
call
call
iorwf
movf
return
GetByte
ASCII2Hex
Temp
Temp,F
GetByte
ASCII2Hex
Temp,F
Temp,W
;This function uses the USART
;Read a character from the USART
;Convert the character to binary
;Store result in high nibble
;Read a character from the USART
;Convert the character to binary
;Store result in low nibble
;Move result into WREG
©
1998 Microchip Technology Inc.
DS91025A-page 5