Self Programming Examples Nec Electronics 78k0kx2 Microcontrollers Application Note
Self Programming Examples Nec Electronics 78k0kx2 Microcontrollers Application Note
On April 1st, 2010, NEC Electronics Corporation merged with Renesas Technology
Corporation, and Renesas Electronics Corporation took over all the business of both
companies. Therefore, although the old company name remains in this document, it is a valid
Renesas Electronics document. We appreciate your understanding.
(Note 1) “Renesas Electronics” as used in this document means Renesas Electronics Corporation and also includes its majority-
owned subsidiaries.
(Note 2) “Renesas Electronics product(s)” means any product developed or manufactured by or for Renesas Electronics.
Application Note
Self-Programming Examples
For NEC Electronics 78K0/Kx2 Microcontrollers
The information in this document is current as of July 2006, however the information is subject to change without
notice. For actual design-in, refer to the latest publications of NEC Electronics data sheets or data books, etc., for the
most up-to-date specifications of NEC Electronics products. Not all products and/or types are available in every
country. Please check with an NEC Electronics sales representative for availability and additional information.
No part of this document may be copied or reproduced in any form or by any means without prior written consent of
NEC Electronics. NEC Electronics assumes no responsibility for any errors that may appear in this document.
NEC Electronics does not assume any liability for infringement of patents, copyrights or other intellectual property
rights of third parties by or arising from the use of NEC Electronics products listed in this document or any other
liability arising from the use of such NEC Electronics products. No license, express, implied or otherwise, is granted
under any patents, copyrights or other intellectual property rights of NEC Electronics or others.
Descriptions of circuits, software and other related information in this document are provided for illustrative purposes
in semiconductor product operation and application examples. The incorporation of these circuits, software and
information in the design of customer's equipment shall be done under the full responsibility of customer. NEC
Electronics no responsibility for any losses incurred by customers or third parties arising from the use of these circuits,
software and information.
While NEC Electronics endeavors to enhance the quality, reliability and safety of NEC Electronics products, customers
agree and acknowledge that the possibility of defects thereof cannot be eliminated entirely. To minimize risks of
damage to property or injury (including death) to persons arising from defects in NEC Electronics products, customers
must incorporate sufficient safety measures in their design, such as redundancy, fire-containment and anti-failure
features.
NEC Electronics products are classified into the following three quality grades: “Standard”, “Special” and “Specific”.
The "Specific" quality grade applies only to NEC Electronics products developed based on a customer-designated
“quality assurance program” for a specific application. The recommended applications of NEC Electronics product
depend on its quality grade, as indicated below. Customers must check the quality grade of each NEC Electronics
product before using it in a particular application.
"Standard": Computers, office equipment, communications equipment, test and measurement equipment, audio and
visual equipment, home electronic appliances, machine tools, personal electronic equipment and industrial robots.
"Special": Transportation equipment (automobiles, trains, ships, etc.), traffic control systems, anti-disaster systems,
anti-crime systems, safety equipment and medical equipment (not specifically designed for life support).
"Specific": Aircraft, aerospace equipment, submersible repeaters, nuclear reactor control systems, life support
systems and medical equipment for life support, etc.
The quality grade of NEC Electronics products is “Standard” unless otherwise expressly specified in NEC Electronics
data sheets or data books, etc. If customers wish to use NEC Electronics products in applications not intended by NEC
Electronics, they must contact NEC Electronics sales representative in advance to determine NEC Electronics 's
willingness to support a given application.
Notes:
1. "NEC Electronics" as used in this statement means NEC Electronics Corporation and also includes its
majority-owned subsidiaries.
2. "NEC Electronics products" means any product developed or manufactured by or for NEC Electronics
(as defined above).
M8E 02.10
ii
78K0/Kx2 Self-Programming
iii
78K0/Kx2 Self-Programming
Revision History
Date Revision Section Description
July 2006 — — First release
iv
78K0/Kx2 Self-Programming
Contents
1. Introduction............................................................................................................................................ 7
1.1 Overview ......................................................................................................................................................7
1.2 Self-Programming Features .......................................................................................................................7
1.3 Requirements...............................................................................................................................................8
4. Self-Programming Example................................................................................................................ 13
4.1 Introduction of Bootloader.......................................................................................................................13
4.2 Elements of Bootloader.............................................................................................................................14
4.2.1 Start-up Signal ..............................................................................................................................14
4.2.2 Execution Signal...........................................................................................................................14
4.2.3 Transferring Code.........................................................................................................................14
4.2.4 Flash Self-Programming...............................................................................................................14
4.2.5 Transferring Control to a Valid Application Program..................................................................15
4.3 Bootloader Configuration and Operation...............................................................................................15
4.3.1 Demonstration Platform................................................................................................................15
4.3.2 Bootloader Communication.........................................................................................................15
4.3.3 Bootloader Operation ...................................................................................................................16
4.3.4 Boot prompt for Loading Application ..........................................................................................17
4.3.5 Loading Application .....................................................................................................................17
4.3.6 Receiving Data .............................................................................................................................17
4.3.7 Processing the Received Data.......................................................................................................17
4.3.8 Blank Checking and Erasing ........................................................................................................18
4.3.9 Programming ................................................................................................................................18
4.3.10 Verifying.......................................................................................................................................18
4.3.11 Storing Valid-Application Checksum...........................................................................................19
4.3.12 Executing Application ..................................................................................................................19
4.3.13 Flash Self-Programming Errors....................................................................................................19
4.3.14 Incorrect Line-Checksum Error....................................................................................................20
4.3.15 Boot Area Overwrite Error ...........................................................................................................20
4.3.16 Boot Swapping .............................................................................................................................20
v
78K0/Kx2 Self-Programming
6. Sample Code......................................................................................................................................... 26
vi
78K0/Kx2 Self-Programming
1. Introduction
The 78K0/Kx2 family of microcontrollers (MCUs) can program their own flash memory. This application
note provides an overview of the flash self-programming capability, using the µP78F0537 microcontroller
as the target device.
For additional information about the 78K0/Kx2 flash self-programming process, refer to the 78K0/Kx2
Flash Memory Self-Programming User’s Manual (document U17516EJxV0UM).
1.1 Overview
To program its flash memory, 78K0/Kx2 MCUs executes code located in hidden ROM. You can call these
hidden functions to check for unused space (blank check) and to erase or write code to any memory
location available in the MCU. To take advantage of these capabilities, your application program must
include code to access the hidden firmware. Thus, you must pre-program the MCU’s flash memory with
this code in order to do self-programming.
7
78K0/Kx2 Self-Programming
1.3 Requirements
Use of General Purpose Register Bank 3
100 bytes of RAM (entry RAM) for a work area for the hidden-ROM functions.
Use of pin FLMD0 to set the MCU to self-programming mode
From 4- to 256 bytes of RAM for a data buffer
Maximum of 39 bytes of RAM for a hidden-ROM function stack
Hidden-ROM functions called by an application program located between addresses 0000H and 7FFFH
As shown in the figure below, the µPD78F0537 MCU’s flash memory is divided into 1-KB blocks. This is
the smallest amount of memory that can be blank-checked, erased, or verified.
07FFFH
Block 31 Other
07C00H (non-Flash)
…
Block 8
02000H
Block 7
01C00H
Block 6 0BFFFH
01800H Bank 5
Block 47
0BC00H
Block 5
01400H Bank 4
…
Block 4
01000H Bank 3
Block 34
08800H
Block 3
00C00H Bank 2
Block 33
08400H
Block 2
00800H Bank 1
Block 32
08000H
Block 1
00400H
Bank 0
Block 0
00000H
Boot Cluster 0 Boot Cluster 1
Common Flash Area
8
78K0/Kx2 Self-Programming
The first eight blocks of flash memory make up two 4-KB boot clusters (Boot Cluster 0 and Boot Cluster
1). These clusters work with the MCU’s boot-swapping feature to allow a bootloader to update itself.
One four-byte word is the smallest amount of memory you can write into the data buffer, which holds a
maximum of 64 words (256 bytes).
The 78K0/Kx2 family includes products with flash memories ranging from 8 to 128 KB. Products with
more than 60 KB of flash memory have a bank configuration. Those with 60 KB or less do not have banks.
For some self-programming operations, such as write, erase or blank-check, you must specify both bank
and block numbers.
The 78K0/Kx2 self-programming capability supports a boot-swap function that replaces the default boot-
program area (Boot Cluster 0) even if the programming is interrupted by electrical noise or power loss. In a
typical application with self-programming, Boot Cluster 0 contains bootloading code with all the necessary
procedures to execute self-programming. To update the bootloader using self-programming, the bootloader
programs its new version into boot cluster 1, then uses the boot-swap feature to have the CPU boot-up using
the new code.
The MCU’s interrupt logic can interrupt self-programming processes such as write or erase. However,
unlike ordinary processing, the interrupt-response time includes a delay to complete processing of the self-
programming library before acknowledging the interrupt. By reading the return value of the self-
programming library, you can determine if you need to retry the procedure stopped by the interrupt.
The flash self-programming function uses a single-voltage process, requiring only the MCU’s VCC power.
The application program manages the FLMD0 pin (which sets the MCU to self-programming mode) as part
of the flash self-programming process. Pin FLMD0 normally is low but must be pulled high for
programming. As shown in the figure below, you can tie FLMD0 to a port pin configured as an output and
9
78K0/Kx2 Self-Programming
to ground via a resistor. In this recommended configuration, you set FLMD0 high or low by setting or
clearing the output-port pin.
78K0/Kx2 MCU
Port Output
FLMD0
R
10K
10
78K0/Kx2 Self-Programming
11
78K0/Kx2 Self-Programming
12
78K0/Kx2 Self-Programming
4. Self-Programming Example
This section describes the code developed by NEC Electronics America to demonstrate the main features of
78K0/Kx2 self-programming. This example uses the UPD78F0537 microcontroller and consists of a
bootloader program, which allows you to update the contents of flash memory by downloading sample
application code from a host PC.
Boot code comprises the instructions that execute when the MCU starts up or boots. The term loading, in
this case, refers to writing new application code into the MCU’s flash memory. Below is the flowchart of a
simple bootloader used to self-program the MCU’s flash memory.
Power-up / Reset
No Valid application
code?
Bootloader
Yes
Execute application
A bootloader lets you update or replace application code without an external programmer, and makes it
possible to update code remotely—over a phone line or Internet connection.
For example, if you have 5,000 MCU-based pay phones and the phones require a firmware update, the
phone company’s service person could manually reprogram the individual telephones—a time-consuming
effort—or use a bootloader to reprogram all 5,000 phones remotely from a central location.
13
78K0/Kx2 Self-Programming
If you have hundreds of vending machines connected to the Internet and want to update their firmware, you
would need to generate a signal to trigger the MCUs to start the bootloading process. The signal could be an
interrupt, a command byte sent over a serial channel, or something else that would cause the program to
reset and run the bootloader code.
Upon startup, the MCU loads a new application program or executes an existing one, depending on the
external signal. You can program the signal to come from a port pin upon power-up, using this signal to
control whether the MCU loads or executes. You could base the signal on a character received by the
UART or a reading taken by an analog-to-digital (A/D) converter.
You can transfer the programming data over an RS-232, I2C, serial port or parallel port. Since the amount
of data transferred typically exceeds the size of the MCU’s RAM, you need some provision to control the
data flow. For an RS-232 serial port you could use a slow baud rate to give the MCU time to process the
data and self-program without being overrun. Or you can use hardware handshaking, using clear to send
(CTS) and request to send (RTS) lines to control the data flow. Another option is software handshaking
using the XON/XOFF protocol.
You can format the code as you choose, but it must contain addressing information as well as checksums
for error processing. Most applications use a standard such as Intel hexadecimal format.
Each time an MCU receives a new batch of data, the device needs to program the correct flash-memory
locations. If the locations are not already blank, the MCU must erase them before programming. Typically
you want to verify the memory contents during or after programming.
14
78K0/Kx2 Self-Programming
After receiving and programming the new code, the bootloader writes a checksum or other unique byte
sequence to a fixed memory location. The bootloader then checks for this value. If it is present, the
bootloader transfers control to the application.
This section describes the bootloader’s configuration and operation while loading new application code,
using a demonstration example.
UPD78F0537 MCU
20-MHz clock
FLMD0 pin tied to ground via a 10K-ohm resistor
P3.0 port-output controls the state of FLMD0 pin
UART6 serial interface
20MHz
X1 X2 VDD
P3.0
UPD78F0537
FLMD0
TX TXD6 R
10K
RX RXD6
GND
The UART6 used by the MCU for transmitting and receiving serial data is configured as follows:
115200 baud
8 data bits
No parity
One stop bit
XON/XOFF flow control
15
78K0/Kx2 Self-Programming
The figure below outlines the Erase, Program, and Verify commands of the application code using
XON/XOFF flow control to download self-programming addresses and data.
Start
Get data
Yes
receive buffer full?
transmit XOFF
No
No
timeout?
Yes
Yes
first time programming data
for current bootload?
blanck check / erase
application flash blocks
No
transmit XON
No
end of file?
Yes
return
16
78K0/Kx2 Self-Programming
When the MCU boots up, either on power-up or after a reset, the device displays the following prompt via
an attached terminal:
NEC Electronics America Bootloader Ver. 1
Load Y/N?
If you enter Y, the device prompts you to download the new application file. The device expects a file in
standard Intel hexadecimal 16 code, as detailed in Appendix C. If you enter N, or if there is no entry for a
number of seconds, the MCU checks for valid application code to execute
When you enter Y at boot-up, the bootloader prompts you to send the file:
Send File
You then can use the Send or Transfer File command in your terminal program to send the file.
The bootloader loads the incoming data into a receive buffer. When the buffer is full, the bootloader
transmits the XOFF character to halt the flow of data and continues to process any remaining data until no
more characters are received. A timeout causes an exit from the receive loop and begins data processing.
Note that the same timeout mechanism comes into play if received characters stop before the receive buffer
is full.
The bootloader examines the data in the receive buffer and executes tasks as follows:
17
78K0/Kx2 Self-Programming
The bootloader processes the receive buffer and stores a start address for programming. The bootloader then
stores data from contiguous addresses into the data buffer. After processing all the data from the receive
buffer or after encountering a break in the address sequence, the bootloader programs the data in the data
buffer. Afterward, the bootloader shifts the data in the receive buffer to move any unprocessed data to the
start of the buffer. The bootloader then transmits the XON character and returns to the receive loop where it
left off. This XON/XOFF receive/programming sequence continues until the bootloader detects the end of
the file.
Caution: The example bootloader provided by NEC Electronics can handle only ‘00’ (data) as the record
type in the Intel Hex 16 format. Refer to Appendix C for details on Intel Hex 16 format. Any other value in
the record type location causes the program to malfunction.
After processing the first data set from the incoming file, the bootloader executes a Blank Check/Erase
command before programming the application code into flash memory. Up to this point, if an error in the
process causes the bootloader to reset, the application flash still valid. The bootloader blank-checks the
flash memory first and only erases blocks that are not blank. If blocks are erased, then the bootloader
outputs the numbers of erased blocks in hexadecimal format:
Erasing 02
Erasing 03
Erasing 1D
4.3.9 Programming
The bootloader programs the data in the buffer by specifying the address and the number of words to be
programmed. Each time the bootloader programs data, it outputs the starting addresses so that you can
monitor the progress, as follows:
Programming at ..
101C
102C
112C
Etc.
4.3.10 Verifying
After receiving and programming the whole file without errors, the bootloader verifies the flash memory
and outputs the message:
Verifying..
18
78K0/Kx2 Self-Programming
When application code is successfully verified, the bootloader stores a 4-byte checksum at the end of flash
memory. This checksum is summed over the entire flash application area, from the start of
FIRST_FLASH_BLOCK_C to the end of LAST_FLASH_BLOCK_B, excluding the four bytes used for
checksum storage. Since the UPD78F0537 microcontroller has 128 KBytes of flash memory, the last block
(47) of bank 5 stores the checksum:
#define FIRST_FLASH_BLOCK_C 4 // first application block
#define LAST_FLASH_BLOCK_B 47 // last application block
After programming the checksum in normal mode, the bootloader verifies the block:
Checksum 00DC8195 at..
BFFC
Verifying..
Note that in this example, the checksum is calculated by summing the data bytes from 1000H to 7FFFH
(common area), 8000H to BFFFH from banks 0 to 4, and 8000H to BFFB from bank 5. The bootloader
stores the checksum as a 4-byte word in the last four locations of block 47, bank 5 (BFFCH, BFFDH,
BFFEH, BFFFH).
Immediately after successfully loading the new application code, the MCU executes the code. Whether the
code is written to run immediately after a bootload, power-up or reset, the bootloader always checks for a
valid application checksum before executing the application code. The bootloader calculates a checksum for
the flash application memory, compares the calculated and stored checksums, then outputs the information
in this form:
Stored checksum = 00DC8195
Calculated checksum = 00DC8195
If the values are equal, the MCU executes the code. Otherwise, the program resets and prompts you to
download a new application. This valid-application check guards against execution of invalid code, which
could happen, for example, if you program an MCU with the bootloader but it has not yet received
application code. Invalid execution can also occur if noise or power loss causes an MCU reset or if one of
these conditions occurs in the middle of a download.
19
78K0/Kx2 Self-Programming
While processing characters in the receive buffer, the bootloader examines each line for the correct
checksum. If an incorrect checksum is found, the bootloader outputs the message:
Line checksum!
The bootloader then enters an endless loop and allows the watchdog timeout to force a reset.
When bootloading a new application and before programming the received data, the bootloader examines
each address to make sure that it falls outside the boot cluster 0 area (0000H–0FFFH). Programming an
address inside this range would corrupt the bootloader code. If an address falls inside this range, the
bootloader outputs the message:
Boot Area!
The bootloader then enters an endless loop and allows the watchdog timeout to force a reset.
Replacing the bootloader in a microcontroller requires use of a procedure called boot swapping. This
procedure involves two bootloaders—one already stored in the MCU’s boot cluster and the new bootloader
that needs to be stored in the boot cluster. The following boot-swapping steps refer to these bootloaders as
A and B, respectively:
Bootloader A examines the first address of the file being sent. If the address is the reset address of
0000H, the bootloader knows that the file contains new bootloader code rather than an application.
Bootloader A then erases boot cluster 1 (blocks 4 to 7).
Although Bootloader B (the new bootloader) has addresses in the 0000H–0FFFH range (Boot Cluster
0), the Bootloader A must store the new code in the 1000H–1FFFH range (Boot Cluster 1). Bootloader
A thus adds the offset 1000H to all addresses before programming.
After programming area 1000H to 1FFFH, Bootloader A prompts you to replace the bootloader code. If
you decide to replace Bootloader A, it sets the boot-swap flag and forces the MCU to reset by allowing
the watchdog timer to overflow.
On reset, the MCU sees that the boot-swap flag is set and starts execution from Boot Cluster 1
(Bootloader B).
Bootloader B checks the boot-swap flag. If the flag is set, Bootloader B erases Boot Cluster 0
(Bootloader A) and copies itself into that area.
After copying from Boot Cluster 1 to Boot Cluster 0, Bootloader B clears the boot-swap flag and allows
the watchdog timer to overflow to force another reset.
20
78K0/Kx2 Self-Programming
Upon this new reset, the MCU sees that the boot-swap flag is cleared and starts execution from Boot
Cluster 0 (Bootloader B).
Based on the boot-swap flag, the application starts at 0000H or 1000H.
This example does not include any interrupt servicing.
Figure 7. Boot-Swapping Steps
1FFFH 1FFFH
BLOCK 7 BLOCK 7
BLOCK 6 Program BLOCK 6
Erase cluster 1 cluster 1
BLOCK 5 BLOCK 5
1000H BLOCK 4 1000H BLOCK 4
RESET 0FFFH 0FFFH
BLOCK 3 BLOCK 3
BLOCK 2 BLOCK 2
Bootloader A Bootloader A
BLOCK 1 BLOCK 1
executing executing
BLOCK 0 BLOCK 0
0000H 0000H
Step 1 Step 2
1FFFH 1FFFH
BLOCK 7 BLOCK 7
Bootloader B BLOCK 6 BLOCK 6
executing BLOCK 5 BLOCK 5
RESET 1000H BLOCK 4 RESET 1000H BLOCK 4
0FFFH BLOCK 3 0FFFH
BLOCK 3
BLOCK 2 BLOCK 2
Erase cluster 0
and copy cluster 1 BLOCK 1 Bootloader A
BLOCK 1
executing
BLOCK 0 BLOCK 0
0000H 0000H
Step 3 Step 4
21
78K0/Kx2 Self-Programming
To take full advantage of flash self-programming, separate your code into two sections: the boot area and
the application area. This separation allows you to update the application code without disrupting a
bootloader program. In addition, you can update the bootloader itself with the MCU’s boot-swapping
capability.
Boot Code
Self-programming functions
Downloading functions
Other routines…
+ Application Code
The typical development flow for generating code with self-programming capabilities using NEC
Electronics tools is shown below.
22
78K0/Kx2 Self-Programming
Build Code
NEC Electronics’ tool suites provide everything necessary to develop code with self-programming
functionality. You can easily create self-programming code with the compiler, linker and object converter
options provided by NEC Electronics’ PM Plus Integrated Development Environment (IDE) user interface.
Below is a description of the minimum number of steps that you can follow to generate boot and application
code with NEC Electronics tools’ default options. For details on this procedure, refer to the CC78K0 and
RA78K0 Language and Operation Manuals.
23
78K0/Kx2 Self-Programming
3. Specify the starting address of application code (default value should be 2000H).
Notes:
If the application code starts at an address other then 2000H, you must rebuild the NEC Electronics run-
time libraries. Read the steps described in the CC78K0 Language User’s Manual for more details.
The bootloader example developed by NEC Electronics America uses 1000H as the application code
start address.
24
78K0/Kx2 Self-Programming
2. Select the setting in PM Plus to output object code for flash memory (application code). This setting
automatically selects the correct C startup routine for flash code, as shown below.
3. In the Object Converter options, specify that the tool generate two separate HEX files, one for boot
code and one for application (flash) code.
Note that file *.HXB should match file *.HEX generated from boot code build.
25
78K0/Kx2 Self-Programming
6. Sample Code
The demonstration program consists of software modules made up of the files shown in the table below.
The table indicates which files the Applilet generates and which you have to modify.
Three sub-project files are associated with this application. To configure them, create three sub-directories
under the main directory for dice6, ADC6 and bootloader. Copy adcbu6.c and uart6.h to the dice directory.
Copy adcbu6.c and uart6.h to the ADC directory. Copy the rest of the files (including uart6.h) to the
bootloader directory. In the main directory, create the main project and add new projects individually into
the main project. After making the project, you get the project file settings shown below.
26
78K0/Kx2 Self-Programming
27
78K0/Kx2 Self-Programming
7.1 bloader.c
/***************************************************************************
*
* FILE : bloader.c
* DATE : February 2006
* DESCRIPTION : boot main file for M-78F0537
* CPU TYPE : 78K0/KE2 - uPD78F0537D
*
* Notes: :
*
***************************************************************************/
#pragma sfr
#pragma NOP
#pragma EI
#pragma DI
// defines
#define VERSION 3
#define SSEG_L 0xc7
/*=======================================
; include files
;======================================*/
#include "getdata.h"
#include "epvdata.h"
#include "uart6.h"
/***************************************************************************/
// void hdwinit(void) - set up initial hardware
// note - this is called by startup code before boot_main() is called
void hdwinit ()
{
/* note that WDTON in option byte (option.asm) is 1, so */
/* watchdog timer is enabled on reset */
28
78K0/Kx2 Self-Programming
/****************************************************/
void boot_main(void) // reserved word "boot_main"
{
unsigned char delay;
P4=0x03; // "b"
P5=0x08;
P7=led_array[VERSION]; // version of bootloader example
PM4=0x00;
PM5=0x00;
PM7=0x00; // set port to all outputs
Tx_CRLF();
Tx_Word(wordData);
wordData=(unsigned int)(validAppWord&0x0000ffff);
Tx_Word(wordData);
31
78K0/Kx2 Self-Programming
7.2 epvdata.c
/***************************************************************************
*
* FILE : epvdata.c
* DATE : February 2006
* DESCRIPTION : bootload file for M-78F0537
* CPU TYPE : 78K0/KE2 - uPD78F0537D
*
* Notes: : supporting routines for erase program verify routines
* : plus checksum calculation and storage
*
***************************************************************************/
#define EPVDATA_C
#pragma sfr
#pragma NOP /* key word for NOP instruction */
#pragma DI
#include "epvdata.h"
#include "uart6.h"
struct stGetInfo{
UCHAR OptionNumber;
UCHAR GetInfoBank;
UCHAR GetInfoBlock;
};
32
78K0/Kx2 Self-Programming
void programDataBuffer(void)
{
WDTE=0xac; // clear watchdog timer
}
startAddress=(unsigned short)(programmingAddress); // get write start address
void Enable_SFP(void)
33
78K0/Kx2 Self-Programming
{
FLMD0_CONTROL_IO=OUTPUT; // set FLMD0 control pin to output
FLMD0_CONTROL_PIN=1; // set FLMD0 high
FlashStart();
FlashEnv((unsigned short)&myEntryRam);
// check mode is ok
returnValue=CheckFLMD();
void Disable_SFP(void)
{
FLMD0_CONTROL_PIN=0; // set FLMD0 pin low
FlashEnd();
}
void EraseFlashBlocks(unsigned char firstBank, unsigned char lastBank, unsigned char firstBlock, unsigned char
lastBlock)
{
unsigned char blocknumber, banknumber;
WDTE=0xac; // clear watchdog timer
}
}
else // else if blank check
error
{
Tx_String("\n\rSFP Error: BLOCK BLANK CHECK: "); // transmit
function return code
Tx_Byte(returnValue); // return from function
}
}
}
}
}
WordAddr.WriteAddress = writeAddress;
WordAddr.WriteBank = banknumber;
}
}
void VerifyFlashBlocks(unsigned char firstBank, unsigned char lastBank, unsigned char firstBlock, unsigned char
lastBlock)
{
unsigned char blocknumber, banknumber;
WDTE=0xac; // clear watchdog timer
Tx_String("\n\rVerifying..\n\r");
if(returnValue!=0) // if not
successful
{
Tx_String("\n\rSFP Error: BLOCK VERIFY: "); // transmit
function return code
Tx_Byte(returnValue); // return from
function
}
}
}
}
for(bank=0;bank<6;bank++){
BANK=bank;
void WriteVerifyAppCheckSum(void)
{
WDTE=0xac; // clear
watchdog timer
VerifyFlashBlocks(CS_FLASH_BANK,CS_FLASH_BANK,CS_FLASH_BLOCK,CS_FLASH_BLOCK);
// verify block
WDTE=0xac; // clear watchdog timer
}
for(i=0;i<25;i++)
{
WDTE=0xac; // clear watchdog timer
timeOut=MAX_COUNT;
while(timeOut>0) // wait for user to confirm
{
if(SRIF6)
{
rx_char=Rx_Character(); // get character
Tx_Character(rx_char); // echo character
if((rx_char=='y')||(rx_char=='Y')) // if yes
{
return(TRUE); // return true
}
else
{
if((rx_char=='n')||(rx_char=='N')) // if no
{
return(FALSE); // return FALSE
}
else // if input but not yes or no
{
i=0; // restart timeout loop
}
}
}
GetInfo.OptionNumber=0x04;
GetInfo.GetInfoBank=0; //don't care when Option = 4
GetInfo.GetInfoBlock=0; //don't care when Option = 4
returnValue=FlashGetInfo(&GetInfo,&myDataBuffer);
{
Tx_String("\n\rSFP Error: GET INFORMATION: "); // transmit function return code
Tx_Byte(returnValue); // return from function
}
return(myDataBuffer[0]); // return information
}
void performBootSwap(void)
{
unsigned char blocknumber,j;
}
}
void ToggleBootSwapFlag(void)
{
returnValue=FlashSetInfo(0xFE); // write 0 to boot swap flag (bit 0)
38
78K0/Kx2 Self-Programming
7.3 getdata.c
/***************************************************************************
*
* FILE : getdata.c
* DATE : February 2006
* DESCRIPTION : bootload file for M-78F0537
* CPU TYPE : 78K0/KE2 - uPD78F0537D
*
* Notes: :
*
***************************************************************************/
#define GETDATA_C
#pragma sfr
#pragma NOP
#pragma DI
#include "getdata.h"
#include "epvdata.h"
#include "uart6.h"
// flags
unsigned char firstXOFF; // flag for first XOFF
unsigned char endOfFile; // flag for end of file
unsigned char breakFlag; // flag for break in address
// receive data
unsigned char rx_buffer[RB_SIZE]; // buffer to hold received data
unsigned int rb_index; // index for receive buffer
unsigned char flowState; // flow state
// record
unsigned char recordCount; // number of data bytes in line
unsigned char msAddress; // most significant byte of line address
unsigned char lsAddress; // least significant byte of line address
unsigned char recordType; // record type (00=data, 01=end of file)
unsigned char checkSum; // checksum for line
// processing data
unsigned int pr_index; // index used for processing
unsigned int pr_end; // end index for processing loop
unsigned char charPosition; // character position in line
unsigned char nextByte; // next byte in buffer
unsigned char sumOfBytes; // sum of bytes to verify checksum
unsigned char dataCount; // count of remaining data bytes in line
unsigned char sob_whole; // sum of bytes up to last whole sfp word
unsigned int rb_whole; // index at last whole sfp word
unsigned char dc_whole; // data count at last whole sfp word
// addresses
unsigned char oddAddress; // bytes greater than sfp word boundary
unsigned int currentAddress; // current address of data
unsigned int lineAddress; // received address of current line
39
78K0/Kx2 Self-Programming
// general use
unsigned int int_j; // integer j
void GetFile(void)
{
WDTE=0xac; // clear watchdog timer
//initialise variables
firstProgram=TRUE; // first time programming is true
firstXOFF=TRUE; // first XOFF is true
endOfFile=FALSE; // end of file is false
breakFlag=FALSE; // address break flag is false
bootDownLoad=FALSE; // boot download is false
rb_index=0; // receive buffer index is 0
charPosition=0; // line character position is 0
Tx_Character(X_ON); // ensure in XON state
flowState=X_ON; // set flow state to XON
Tx_String("\n\rSend file\n\r"); // ask user to send file
{
myDataBuffer[int_i]=0x00; // clear data buffer
}
pr_index=0; // reset process receive buffer index
}
}
}
else
{
if(firstXOFF) // if file has no leading
colon
{
while(1); // wait for
watchdog timeout
}
}
break;
case 1:
recordCount=GetHexByte(); // get record count
charPosition=3; // next char position is 3
41
78K0/Kx2 Self-Programming
case 3:
msAddress=GetHexByte(); // get ms byte of address
charPosition=5; // next char position is 5
sumOfBytes+=msAddress; // add to sum of bytes
break;
case 5:
lsAddress=GetHexByte(); // get ls byte of address
charPosition=7; // next char position is 7
sumOfBytes+=lsAddress; // add to sum of bytes
lineAddress=(unsigned int)msAddress<<8; // put ms byte in line
address
lineAddress|=(unsigned int)lsAddress; // put ls byte in line
address
if(firstXOFF) // is this the first XOFF
{
}
else // if its not the
first XOFF
{
while((currentAddress<lineAddress)&&(oddBytes!=0))
{
myDataBuffer[db_index++]=0xff; // put in pad
byte
currentAddress++; // increment current
address
oddBytes++; // increment odd
bytes
oddBytes=oddBytes%4;// see if they make up a
whole word
42
78K0/Kx2 Self-Programming
}
if((oddBytes==0)&& (currentAddress<lineAddress))
{
breakFlag=TRUE; // set break flag to true
currentAddress=lineAddress; // set new
current address to break address
for(int_i=0,int_j=pr_index;int_j<RB_SIZE;int_i++,int_j++)
{
rx_buffer[int_i]=rx_buffer[int_j]; // shift
buffer data
}
rb_index-=pr_index; // shift buffer index
programDataBuffer();
pr_index=pr_end; // exit loop if
break flag set
}
}
break;
case 7:
recordType=GetHexByte(); // get record type
if(recordType!=0)endOfFile=TRUE; // if not 0 then assume
end of file
sumOfBytes+=recordType; // add to sum of bytes
charPosition=9; // next char position is 9
break;
case 9:
if(dataCount!=0) // if still data bytes remaining in line
{
nextByte=GetHexByte(); // get next data byte
sumOfBytes+=nextByte; // add to sum of bytes
myDataBuffer[db_index++]=nextByte; // put byte in
data buffer
currentAddress++; // increment current
address
dataCount--; // decrement
data count
oddBytes=(unsigned char)(db_index%4); //
caluculate odd bytes
if(oddBytes==0) // if whole
number of sfp words
{
rb_whole=pr_index; // save index
sob_whole=sumOfBytes; // save sum of bytes
dc_whole=dataCount; // save data
count
}
}
else
43
78K0/Kx2 Self-Programming
{
charPosition=11; // checksum at position
>=11
}
break;
case 11:
checkSum=GetHexByte(); // get checksum
default:
NOP(); // no action
} // end switch
} // end while(pr_index<pr_end)
}
else // else if index <
data limit
{
44
78K0/Kx2 Self-Programming
} // end while(!endOfFile)
{
ToggleBootSwapFlag(); // set the boot swap flag
bootSwapFlag=CheckBootSwapFlag(); // check status of boot swap flag
}
Disable_SFP(); // disable self-flash programming
P4=0x0F; // "r"
P5=0x0A;
P7=0x86; // "E"
}
/***************************************************************************
*
* Function: GetHexByte
* Parameters: none
* Returns: hex byte from char array
* rx_buffer[pr_index],rx_buffer[pr_index+1]
* Date: January 24, 2005
* Notes: increments entry value of pr_index by 2
*
***************************************************************************/
46
78K0/Kx2 Self-Programming
7.4 uart6.c
/***************************************************************************
*
* FILE : uart6.c
* DATE : November 17, 2004
* DESCRIPTION : UART file for M-78F0537
* CPU TYPE : 78K0/KE2 - 78F0537D
*
* Notes: : UART6 (8 data bits, no parity, 1 stop bit)
*
***************************************************************************/
#define UART6_C
#pragma sfr
#pragma NOP /* key word for NOP instruction */
#include "uart6.h"
CKSR6 = 0x00;
ASIM6 |= 0xE5;
47
78K0/Kx2 Self-Programming
/***************************************************************************
48
78K0/Kx2 Self-Programming
*
* Function: Tx_CRLF
* Parameters: none
* Returns: nothing
* Date: February 28, 2004
* Description: Send CR/LF
*
* Notes:
*
***************************************************************************/
void Tx_CRLF(void)
{
Tx_Character(CR_CHAR); // transmit carriage return char
Tx_Character(LF_CHAR); // transmit line feed char
}
/***************************************************************************
*
* Function: Tx_Character
* Parameters: unsigned ASCII character
* Returns: nothing
* Date: February 23, 2004
* Description: Transmits character via UART
*
* Notes:
*
*
***************************************************************************/
void Tx_Character(char ascii_character)
{
char clear_char;
/***************************************************************************
*
* Function: Rx_Character
* Parameters: none
* Returns: received character
* Date: February 23, 2004
* Description: Receives character via UART
*
* Notes: INTSER0 set if receive error
* Reading RXB6 clears ASIS6 error flags
49
78K0/Kx2 Self-Programming
}
}
50
78K0/Kx2 Self-Programming
7.5 adcbu6.c
/***************************************************************************
*
* FILE : adcbu6.c
* DATE : February 2006
* DESCRIPTION : adc demo file for M-Station M-78F0537
* CPU TYPE : 78K0/KE2 - 78F0537
*
* Notes: : For use with bootloader
* : assumes boot code has already initialized micro & UART
*
***************************************************************************/
#define HEX_DISPLAY 0
#define VOLT_DISPLAY 1
void main(){
unsigned int i;
DI(); // disable interrupts
51
78K0/Kx2 Self-Programming
if (volts!=old_volts){
Tx_Character(CR_CHAR);
Tx_Character(0x30+led1_value);
Tx_Character('.');
Tx_Character(0x30+led2_value);
Tx_Character('V');
old_volts=volts;
}
}
if(adc_msbyte!=old_adcval){
Tx_Character(CR_CHAR);
Tx_Byte(adc_msbyte);
Tx_Character('H');
Tx_Character(' ');
old_adcval=adc_msbyte;
}
}
if((SWITCH_2==0)&& (SWITCH_3==1))
{
display_state=VOLT_DISPLAY; // display mode is volts
}
if((SWITCH_2==1)&& (SWITCH_3==0))
{
display_state=HEX_DISPLAY; // display mode is hex
}
for(tcnt=0;tcnt<40;tcnt++)
{
WDTE=0xac; // clear watchdog timer
if(received_char=='y' || received_char=='Y')
{
bootRequest=1; // if yes set boot request flag
tcnt=40; // and set tcnt for exit
}
else // if not yes
{
if(received_char=='n' || received_char=='N')
{
bootRequest=0; // if no clear boot request flag
tcnt=40; // and set tcnt for exit
}
else
{
bootRequest=0; // clear boot request flag
}
}
}
timedowncount--; // decrement timout count
}
}
}
else // if not a boot request transmit returning to application message
{
Tx_String("\n\rReturned to ADC Display Demo on M-Station\n\r");
Tx_String("(Hit any key to get bootloader prompt)\n\r\n\r");
}
54
78K0/Kx2 Self-Programming
Delay(5000); // delay
}
}
for(i=0;i<delay;i++);
}
/***************************************************************************
*
* Function: UartRx_Interrupt
* Parameters: none
* Returns: nothing
* Date: March 12, 2004
* Description: Interrupt service routine for UART6 reception
*
* Notes: Used for bootloader request
*
***************************************************************************/
55
78K0/Kx2 Self-Programming
7.6 dicebu6.c
/***************************************************************************
*
* FILE : dicebu6.c
* DATE : February 2006
* DESCRIPTION : dice demo file for M-Station M-78F0537
* CPU TYPE : 78K0/KE2 (uPD78F0537D)
*
* Notes: : For use with bootloader
* : assumes boot code has already initialized micro & UART
* : Uses interrupts and includes library files
*
***************************************************************************/
// pragmas
#pragma ext_table 0x2000
#pragma SFR
#pragma NOP
#pragma DI
#pragma EI
#pragma interrupt INTSR6 UartRx_Interrupt rb1
#pragma interrupt INTTM50 TM50_Interrupt rb2
// included files
#include "uart6.h"
#include <stdlib.h>
// defines
#define SWITCH_2 P3.1
#define SWITCH_3 P3.2
// function declarations
void InitTimer50(void);
void StartTimer50(void);
// variables
unsigned char int_count;
unsigned char led1_count;
unsigned char led2_count;
unsigned char led_index;
unsigned char dp_LED2;
unsigned int adc_result;
unsigned char adc_msbyte;
unsigned char ledcycle_speed;
unsigned int gp_int2;
unsigned int gp_int3;
unsigned int rand2;
unsigned int rand3;
unsigned int loop_count;
unsigned char doublesix;
56
78K0/Kx2 Self-Programming
void main(){
unsigned int i;
DI(); // disable interrupts
P4=0xff;
P5=0xff;
P7=0x00; // set 7 segment led2 outputs off
while(1){
WDTE=0xac; // clear watchdog timer
loop_count++; // increment loop count
{rand2=rand(); gp_int2=rand2;} // get random number 2
{rand3=rand(); gp_int3=rand3;} // get random number 3
NOP(); // no operation
Tx_String("Current Roll speed for double six = "); // transmit roll speed
Tx_Byte(adc_msbyte); // value of ms byte of adc result
Tx_CRLF(); // go to new line
Tx_String("Highest Roll speed for double six = "); // transmit roll speed
Tx_Byte(highrollspeed); // value of highest roll speed
Tx_CRLF(); // go to new line
Tx_CRLF(); // go to new line
for(tcnt=0;tcnt<40;tcnt++)
{
WDTE=0xac; // clear watchdog timer
if(received_char=='y' || received_char=='Y')
{
bootRequest=1; // if yes set boot request flag
tcnt=40; // and set tcnt for exit
}
else // if not yes
{
if(received_char=='n' || received_char=='N')
{
bootRequest=0; // if no clear boot request flag
tcnt=40; // and set tcnt for exit
}
else
{
bootRequest=0; // clear boot request flag
}
}
}
/***************************************************************************
*
* Function: UartRx_Interrupt
* Parameters: none
* Returns: nothing
* Date: January 21, 2005
* Description: Interrupt service routine for UART6 reception
*
* Notes: Used for bootloader request
*
***************************************************************************/
/***************************************************************************
*
* Function: TM50_Interrupt
* Parameters: none
* Returns: nothing
* Date: January 21, 2005
* Description: Interrupt service routine for timer 50
*
* Notes: Used for switch debouncing
*
***************************************************************************/
// if not double six set double six and speed reported flags to 0
if((led1_count!=6) || (led2_count!=6)){doublesix=0;speedreported=0;}
}
}
if((int_count&0x07)==0) // for every 8th interrupt
{
if(SWITCH_2==0) // if switch 2 is pressed
{
}
if(SWITCH_3==0) // if switch 3 is pressed
{
led2_count=(unsigned char)gp_int3; // get led2 count
led2_count&=0x07; // use 3 ls bits
if(led2_count>6)led2_count=1; // change 7 result to 1
if(led2_count==0)led2_count=6; // change 0 result to 6
P7=(led_values[led2_count])|dp_LED2; // display led2 count
}
}
}
/***************************************************************************
*
* Function: InitTimer50
* Parameters: none
* Returns: nothing
* Date: January 21, 2005
* Description: Initialises timer/event counter 50
*
61
78K0/Kx2 Self-Programming
* Notes:
*
***************************************************************************/
void InitTimer50(void)
{
TMC50=0x00; // stop timer, clear and start by match with CR50
TCL50=0x07; // set slowest clock frequency
CR50=0xff; // set compare count
PR1L |= 0x02; // set low priority interrupt
TMMK50=1; // mask interrupt
TMIF50=0; // clear interrupt request
}
/***************************************************************************
*
* Function: StartTimer50
* Parameters: none
* Returns: nothing
* Date: January 21, 2005
* Description: Starts timer/event counter 50 and enables interrupt
*
* Notes:
*
***************************************************************************/
void StartTimer50(void)
{
TCE50=1; // start timer 50
TMIF50=0; // clear interrupt request
TMMK50=0; // unmask interrupt
62
78K0/Kx2 Self-Programming
7.7 UART6.h
/***************************************************************************
*
* FILE : UART6.h
* DATE : February 2006
* DESCRIPTION : Uart header file for M-78F0537
* CPU TYPE : 78K0/KE2 - 78F0537D
*
* Notes: :
*
***************************************************************************/
#ifndef _UART6_H
#define _UART6_H
#ifdef UART6_C
#define UART6_GLOBAL
#else
#define UART6_GLOBAL extern
#endif
// character definitions
#define NULL_CHAR 0x00 // NULL character
#define TAB_CHAR 0x09 // Tab character
#define LF_CHAR 0x0a // Line Feed character
#define CR_CHAR 0x0d // Carriage Return character
#define ESC_CHAR 0x1B // Escape character
#define SP_CHAR 0x20 // Space character
#define PROMPT_CHAR '>' // terminal prompt character
#define X_ON 0x11 // XON control
#define X_OFF 0x13 // XOFF control
// function prototypes
void InitUART6_8N1(unsigned char baudRate);
void Tx_String(const char *puc);
void Tx_Word(unsigned int data_16_bit);
void Tx_Byte(unsigned char data_8_bit);
void Tx_CRLF(void);
void Tx_Character(char ascii_character);
char Rx_Character(void);
#endif /* _UART6_H */
63
78K0/Kx2 Self-Programming
7.8 epvdata.h
/***************************************************************************
*
* FILE : epvdata.h
* DATE : February 2006
* DESCRIPTION : bootload headerfile for M-78F0537
* CPU TYPE : 78K0/KE2 - uPD78F0537D
*
* Notes: :
*
***************************************************************************/
#ifndef _EPVDATA_H
#define _EPVDATA_H
#ifdef EPVDATA_C
#define EPVDATA_GLOBAL
#else
#define EPVDATA_GLOBAL extern
#endif
// general definitions
#define FALSE 0
#define TRUE 1
#define OUTPUT 0
#define INPUT 1
// constant definitions
#define MAX_COUNT 0xffff
// application definitions
#define FLMD0_CONTROL_PIN P3.0 // port used to set level on FLMD0 pin
#define FLMD0_CONTROL_IO PM3.0 // port input output configuration
64
78K0/Kx2 Self-Programming
// function prototypes
void programDataBuffer(void);
void Enable_SFP(void);
void Disable_SFP(void);
void EraseFlashBlocks(unsigned char firstBank, unsigned char lastBank, unsigned char firstBlock, unsigned char
lastBlock);
void WriteDataBufferToFlash(unsigned char Banknumber, unsigned short writeAddress,unsigned char wordCount);
void VerifyFlashBlocks(unsigned char firstBank, unsigned char lastBank, unsigned char firstBlock, unsigned char
lastBlock);
unsigned long CalculateAppCheckSum(void);
void WriteVerifyAppCheckSum(void);
unsigned char ConfirmOnPrompt(void);
unsigned char CheckBootSwapFlag(void);
void ToggleBootSwapFlag(void);
void performBootSwap(void);
#endif /* _EPVDATA_H */
65
78K0/Kx2 Self-Programming
7.9 getdata.h
/***************************************************************************
*
* FILE : getdata.h
* DATE : January 17, 2005
* DESCRIPTION : bootload headerfile for M-78F0148H
* CPU TYPE : 78K0/KF1+ - uPD78F0148H
*
* Notes: :
*
***************************************************************************/
#ifndef _GETDATA_H
#define _GETDATA_H
#ifdef GETDATA_C
#define GETDATA_GLOBAL
#else
#define GETDATA_GLOBAL extern
#endif
// function prototypes
void GetFile(void);
unsigned char GetHexByte(void);
#endif /* _GETDATA_H */
66
78K0/Kx2 Self-Programming
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; System : Self programming library(Normal model)
; File name : SelfLibrary_normal.asm
; Version : 2.00
; Target CPU : 78K0/Kx2
; Last updated : 2005/07/08
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PUBLIC _FlashStart
PUBLIC _FlashEnd
PUBLIC _FlashEnv
PUBLIC _FlashBlockErase
PUBLIC _FlashWordWrite
PUBLIC _FlashBlockVerify
PUBLIC _FlashBlockBlankCheck
PUBLIC _FlashGetInfo
PUBLIC _FlashSetInfo
PUBLIC _CheckFLMD
;PUBLIC _EEPROMWrite ;not needed for Self-programming example (removed from code)
;---------------------------------------------------------------------
; EQU settings
;---------------------------------------------------------------------
FLASH_ENV EQU 00H ;Initialization
FLASH_BLOCK_ERASE EQU 03H ;Block erace
FLASH_WORD_WRITE EQU 04H ;Word write
FLASH_BLOCK_VERIFY EQU 06H ;Block verify
FLASH_BLOCK_BLANKCHECK EQU 08H ;Block blank check
FLASH_GET_INF EQU 09H ;Flash memory information read
FLASH_SET_INF EQU 0AH ;Flash memory information setting
FLASH_CHECK_FLMD EQU 0EH ;Mode check
FLASH_EEPROM_WRITE EQU 17H ;EEPROM write
SELF_PROG CSEG
;-------------------------------------------------------------------
; Function name : _FlashStart
; Input : None
; Output : None
; Destroyed register : None
; Summary : Self programming start processing.
;-------------------------------------------------------------------
_FlashStart:
MOV PFCMD,#0A5H ;PFCMD register control
MOV FLPMC,#001H ;FLPMC register control (set value)
MOV FLPMC,#0FEH ;FLPMC register control (inverted set value)
MOV FLPMC,#001H ;FLPMC register control (set value)
RET
67
78K0/Kx2 Self-Programming
;-------------------------------------------------------------------
; Function name : _FlashEnd
; Input : None
; Output : None
; Destroyed register : None
; Summary : Self programming end processing.
;-------------------------------------------------------------------
_FlashEnd:
MOV PFCMD,#0A5H ;PFCMD register control
MOV FLPMC,#000H ;FLPMC register control (set value)
MOV FLPMC,#0FFH ;FLPMC register control (inverted set value)
MOV FLPMC,#000H ;FLPMC register control (set value)
RET
;-------------------------------------------------------------------
; Function name : _FlashEnv
; Input : AX=Entry RAM address
; Output : None
; Destroyed register : None
; Summary : Initialization processing of self programming.
;-------------------------------------------------------------------
_FlashEnv:
;Initialization processing
PUSH PSW ;Save register bank in STACK.
PUSH AX
SEL RB3 ;Sets to register bank 3.
POP HL ;Sets Entry RAM address to HL register
MOV C,#FLASH_ENV ;Sets function number to C register
CALL !8100H ;Calls flash firmware
MOV A, #09H
MOV [HL+13H], A ;Set Block Erase Retry Number
MOV [HL+14H], A ;Set Chip Erase Retry Number
;-------------------------------------------------------------------
; Function name : _FlashBlockErase
; Input : AX=Erase bank
; STACK=Erase block number
; Output : BC=Status
; Destroyed register : AX,BC
; Summary : Erases of specified block (1K byte).
;-------------------------------------------------------------------
_FlashBlockErase:
PUSH HL
CALL !ExchangeBlockNum ;Block number is calculated from block number and bank.
;(Return A=Erase block number after it calculates)
BZ $FBE_PErr ;It is error if the bank number is outside the range.
;Parameter error
FBE_PErr:
MOV A,#FLASHFIRM_PARAMETER_ERROR ;Sets parameter error to return value
FlashBlockErase00:
MOV C,A
MOV B,#00H
POP HL
RET
;-------------------------------------------------------------------
; Function name : _FlashWordWrite
; Input : AX=Address of writing beginning address structure
; (Member of structure...Writing starting address
; Bank of writing starting address)
; STACK1=Number of writing data
; STACK2=Address in writing data buffer
; Output : BC=Status
; Destroyed register : AX,BC,DE
; Summary : Data on RAM is written in the flash memory.
; 256 bytes or less (Every 4 bytes) are written at a time.
;-------------------------------------------------------------------
_FlashWordWrite:
PUSH HL
;Parameter error
FWW_PErr:
MOV A,#FLASHFIRM_PARAMETER_ERROR ;Sets parameter error to return value
FlashWordWrite00:
MOV C,A
MOV B,#00H
POP HL
RET
;-------------------------------------------------------------------
; Function name : _FlashBlockVerify
; Input : AX=Verify bank
; STACK=Verify block number
; Output : BC=Status
; Destroyed register : AX,BC
; Summary : Internal verify of specified block (1K byte).
;-------------------------------------------------------------------
_FlashBlockVerify:
PUSH HL
MOVW BC,AX
MOVW AX,SP
MOVW HL,AX
MOV A,[HL+4] ;Read STACK data(=Verify block number)
MOV B,A
MOV A,C ;A...Verify bank, B...Verify block number
CALL !ExchangeBlockNum ;Block number is calculated from block number and bank.
;(Return A=Verify block number after it calculates)
BZ $FBV_PErr ;It is error if the bank number is outside the range.
;Parameter error
FBV_PErr:
MOV A,#FLASHFIRM_PARAMETER_ERROR ;Sets parameter error to return value
FlashBlockVerify00:
MOV C,A
MOV B,#00H
POP HL
RET
;-------------------------------------------------------------------
; Function name : _FlashBlockBlankCheck
; Input : AX=Blank check bank
; STACK=Blank check block number
; Output : BC=Status
; Destroyed register : AX,BC
; Summary : Blank check of specified block (1K byte).
;-------------------------------------------------------------------
_FlashBlockBlankCheck:
PUSH HL
;Calculate Blank check block number from block number and bank.
MOVW BC,AX
MOVW AX,SP
MOVW HL,AX
MOV A,[HL+4] ;Read STACK data(=Blank check block number)
MOV B,A
MOV A,C ;A...Blank check bank, B...Blank check block number
CALL !ExchangeBlockNum ;Block number is calculated from block number and bank.
;(Return A=Blank check block number after it calculates)
71
78K0/Kx2 Self-Programming
;Parameter error
FBBC_PErr:
MOV A,#FLASHFIRM_PARAMETER_ERROR ;Sets parameter error to return value
FlashBlockBlankCheck00:
MOV C,A
MOV B,#00H
POP HL
RET
;-------------------------------------------------------------------
; Function name : _FlashGetInfo
; Input : AX=Address of flash information acquisition structure
; (Member of structure...Option number
; Bank
; Block number)
; STACK=The first address in buffer where get data is stored
; Output : BC=Status
; Destroyed register : AX,BC,DE
; Summary : The set up information of the flash memory is read.
;-------------------------------------------------------------------
_FlashGetInfo:
PUSH HL
;Calculate Address from Storage buffer and bank.Nothing to do when Option number = 3or4 or Bank = 0
;or Block number(Previous) < 32 or Block number(Previous) >= 48.
;A=Option number, B=Bank, C...Block number(Previous), DE=Storage buffer first address of get data
73
78K0/Kx2 Self-Programming
;Calculation of address(40H*Bank is pulled from address in two high rank bytes.Lower address is the state as it is.)
XCHW AX,DE
MOVW HL,AX
MOV A,[HL+1]
MOV X,A
MOV A,[HL+2] ;A...Most higher address, X...Higher address
XCHW AX,DE ;A...Bank, D...Most higher address, E...Higher address
MOV [HL+2],A ;Sets Storage buffer+2 to Bank.
MOV X,#0
ROL A,1
ROL A,1
ROL A,1
ROL A,1
ROL A,1
ROLC A,1
XCH A,X
ROLC A,1 ;AX=40H*Bank
XCHW AX,DE
XCH A,X
SUB A,E
XCH A,X
SUBC A,D
MOV A,X
MOV [HL+1],A ;Sets Storage buffer+1 to Calculated address(higher).
ReturnAddress_end:
;-------------------------------------------------------------------
; Function name : _FlashSetInfo
; Input : AX=Flash information data
; Output : BC=Status
; Destroyed register : A,BC
; Summary : Setting of flash information.
;-------------------------------------------------------------------
_FlashSetInfo:
74
78K0/Kx2 Self-Programming
;-------------------------------------------------------------------
; Function name : _CheckFLMD
; Input : None
; Output : BC=Status
; Destroyed register : A,BC
; Summary : Checks voltage level of FLMD pin.
;-------------------------------------------------------------------
_CheckFLMD:
;Set infomation processing
PUSH PSW ;Save register bank in STACK.
SEL RB3 ;Sets to register bank 3.
MOV C,#FLASH_CHECK_FLMD ;Sets function number to C register
CALL !8100H ;Calls flash firmware
POP PSW ;Restores register bank from STACK.
;-------------------------------------------------------------------
; Function name : ExchangeBlockNum
; Input : A=Bank
; B=Block number
; Output : A=Block number(New)
; B=Bank
; C=Block number(Previous)
; Summary : Block number is converted into the real address
; from bank information.
75
78K0/Kx2 Self-Programming
;-------------------------------------------------------------------
ExchangeBlockNum:
;It calculates from 32 to 47 block number.
XCH A,B
CMP A,#32
BC $EBN_end
CMP A,#48
BNC $EBN_end
;Bank error
EBN_error_end:
MOV A,#BANK_BLC_ERROR ;Return error number
EBN_end:
CMP A,#BANK_BLC_ERROR ;Bank error ?
RET
;-------------------------------------------------------------------
; Function name : ExchangeAddress
; Input : AX=Address of writing beginning address structure
; (Member of structure...Writing starting address
; Bank of writing starting address)
; Output : AX=Writing starting address(Address in two high rank bytes)
; C=Writing starting address(Lower address)
; Summary : Writing starting address of structure is converted
; into the real address from bank information.
;-------------------------------------------------------------------
ExchangeAddress:
PUSH HL
;Calculation of address(Bank*40H is added to address in two high rank bytes.Lower address is the state as it is.)
MOV D,A
XCH A,X
MOV C,A
MOV X,#0
MOV A,[HL+2] ;Read data from writing beginning address structure
;(=Bank of writing starting address)
CMP A,#6
BNC $EA_error_end
ROL A,1
ROL A,1
ROL A,1
ROL A,1
ROL A,1
ROLC A,1
XCH A,X
ROLC A,1 ;AX=40H*Bank
XCH A,X
ADD A,D ;Addition of Higher address
XCH A,X
ADDC A,#0 ;Addition of Most higher address
;A....Most higher address after it calculates
;X....higher address after it calculates, C...Lower address
BR EA_normal_end
;Bank error
EA_error_end:
MOVW AX,#BANK_ADDR_ERROR
BR EA_normal_end
EA_end:
XCH A,X
MOV C,A
MOV A,#0 ;A....Most higher address after it calculates
;X....higher address after it calculates, C...Lower address
EA_normal_end:
POP HL
CMPW AX,#BANK_ADDR_ERROR ;Bank error ?
RET
END
77
78K0/Kx2 Self-Programming
7.10 option.asm
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; System : Option byte setting
; File name : option.asm
; Version : 0.00
; Target CPU : 78K0/Kx2
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
78