C51 In-System FLASH Programming1.IntroductionMostC51microcontrollerbasedapplicationsusinganon-boardFLASHmemoryforcodeanddatastoragetaketheadvantageofbeingIn-SystemProgrammabledthankstotheFLASHtechnology.ThisapplicationnotedescribesthebasichardwareandsoftwarerequirementstobuildsuchasystembasedonaC51product(orC251productconfiguredforC51memorymodel).BasicIn-SystemProgrammingfeaturesdescribedinthisdocumentare:FLASHidentifying,erasingandprogrammingfromaHEXfile.TheC51/C251DemoBoarddemonstratesthisIn-SystemProgrammingimplementationusinganAtmelAT49HF010FLASHmemory.2.Description2.1.System RequirementsTheIn-SystemFLASHProgramming(ISP)describedinthisdocumentassumesatypicalC51configurationshowninFigure1.UARTC51Data BusFLASHProgramMemorySRAMDataMemoryControlAddr BusControlISPGlueFigure1.TypicalC51ConfigurationThebasicsystemincludesaC51,aFLASHmemoryforcodeandaSRAMfordata.TheC51interfacesthememorydevicesthroughsomeISPdedicatedgluetoallowtheC51towriteintotheFLASHasifitwouldbeaSRAM.TheC51isalsoconnectedtoaterminalviaaRS-232seriallinkusingitsembeddedUART.ThisterminalwillbeusedtodownloadanewprogramintotheFLASHmemory.2.2.Memory MappingC51microcontrollershaveseveralmemoryspaceareas:•••••TheTheTheTheTheinternaldatamemoryinternalSpecialFunctionRegister(SFR)memorytoaddresson-chipresourcesoptionalexpandedon-chipdatamemory(on-chipXRAM)externalprogrammemoryexternaldatamemoryRev A - 21 Jan 20001
ANM076
2.2.1.Standard Program Execution Mode
FFFF
FFFF
UpperOptionalInternalRAMFFSpecialFunctionRegisterdirect accesses80ExternalDataMemoryExternalProgramMemory
Lower128 bytesInternalRamdirect or indirectaccesses000000
SRAMdevice
Optionalon-chipXRAM0000
On-ChipProgramMemory(Disabled)
0000
0000
FLASHdevice
Figure2.C51MemoryMappinginStandardMode
Whentheapplicationisrunning(standardmode),theSRAMisusedforapplicationdatastorageandtheFLASHmemoryforcodeandconstantdatastorage.DatainSRAMareaccessedthankstotheMOVXinstructionandconstantdataareretrievedfromtheFLASHmemorythankstotheMOVC.
2.2.2.ISP Program Execution Mode
FFFF
UpperOptionalInternalRAMFFSpecialFunctionRegisterdirect accessesFFFF
ExternalDataMemory
ExternalProgramMemory
80Lower128 bytesInternalRamdirect or indirectaccesses000000
FLASHdevice
Optionalon-chipXRAM0000
On-ChipProgramMemory(ISP Program)
0000
0000
SRAMdevice
Figure3.C51MemoryMappinginISPMode
InISPmode,theFLASHmemoryisre-mappedinthedataspaceareasothatanewprogramcanbewritenusingdatawriteinstructions(MOVX).Inthismode,theFLASHmemoryisnolongeravailableforprogramexecutionandtheISPprogrammustcarriedoutfromtheon-chipprogrammemory.BecausetheC51microcontrollerhasaHarwardarchitecture(separatememorydata/codeaddressspaces)theFLASHmemorycanbeeasilyre-mappedintothedataspaceprovidingasimplelogicglueandfewcontrolsignals.
SomeC51derivativesprovideanextraon-chipdatamemoryareacalledon-chipXRAM.ThisareaisoverlaidwiththeexternaldatamemoryaccessedusingMOVXinstructions.InISPmode,thison-chipXRAMmustbedisabledotherwiseMOVXinstructionwouldnotaccesstoapartoftheFLASHmemorybuttotheon-chipXRAMarea.2
Rev A - 21 Jan 2000
ANM076
2.2.3.Special ConsiderationsInordertosimplifythediscussion,itisassumedthereisnoneedtostoreapplicationroutinesintheon-chipmemoryandtheC51wouldbehaveasaROMlessversion:•Instandardmode,themicrocontrollerwouldresetwithEA#=0andtheapplicationwouldstartfromaddress•0000hlocatedinFLASHmemoryInISPmode,themicrocontrollerwouldresetwithEA#=1andtheISPprogramwouldstartfromaddress0000hintheon-chipROM/EPROMorFLASHmemorydependingonthepart.Howeversomeapplicationsmayrequiretostoresomeextraroutinesintheon-chipmemoryforseveralreasonslikecostreductionusingthesameROMversiononmanydifferentapplications,cryptedROMroutinesforsecuredapplications,auto-configuringapplicationwithon-chipFLASHprogrammemory...Inthislattercase,someroommustbeleftfortheISPsubroutinesandthemicrocontrollerwouldalwaysresetwithEA#=1.TohelptheresetserviceroutinetodeterminewhethertheapplicationisinstandardmodeorISPmode,anextrasignalshouldbeprovidedbytheapplication.NotethataspecialcareshouldbetakenfortheinterruptroutinedesignsincesomeinterruptsvectorsmaybesharedbetweentheISPprogramandtheapplication.3.HardwareFigure4showsthetypicalhardwareconfigurationforanapplicationprovidingtheIn-SystemFLASHProgrammingfeature.TheISPinputsignalconfiguresthesysteminStandardModeorinIn-SystemProgrammingMode.ALEP0AD7:0P3.0/RxDP3.1/TxD573SRAM MEMORYA7:0D7:0RXDTXDRS232InterfaceP2/A15:8P3.6/WR#P3.7/RD#A15:8WRRDOEFLASH MEMORYEA#ISPPSENA7:0D7:0A15:8WRRDOEVSSFigure4.In-SystemProgrammingHardwareConfigurationWhenISPishigh,thestandardmodeisselected.Afterreset,theprogrambranchesataddress0000hwhichislocatedintheon-boardFLASHmemory(EA#=0).WhenISPislow,theISPmodeisselected.Afterreset,theprogrambranchestoaddress0000hlocatedintheon-chipmemoryandexecutestheISPprogram.Rev A - 21 Jan 20003
ANM076
TheISPalsocontrolstheFLASH/SRAMmemoryaddressareaswap.ThedecodingequationsformemorycontrolsignalsareshowninTable1.ThegluelogicthatcontrolsthememorysignalsmaybeprogrammedinaPLD(ProgrammableLogicDevice).Table1.EquationsforMemoryControlOperatingModeFLASHMemory----RD=PSEN&RD#WR=WRRD=PSENWR=1------SRAMMemoryRD=RD#WR=WROE=1RD=XWR=XOE=0ISP=0(In-SystemProgrammingMode)ISP=1(StandardMode)4.SoftwareThesoftwareinchargeoftheISPissplittedintothreeparts:theIOinterface,theIntelHEXfileparserandtheFLASHprogramming.4.1.OperationTheISPprogramperformsthefollowingtasks:•AtmelFLASHauthentification(AT49HF010)•FLASHchiperase•DownloadtheHEXfileandprogramdatatotheFLASHFordemonstrationpurpose,thehostterminaldisplaysthefollowingmessagesduringtheISPaverallprocess:** Welcome to the ISP program! **Check if FLASH device is a Atmel AT49HF010... OK.Erasing the on-board FLASH memory... OK.Ready for FLASH programming.Send .hex file with the following terminal configuration: - ASCII character transmission, - 8 bits, 1 stop, parity none, - XON-XOFF flow control.Waiting for download...........................................................................................................................................................External FLASH memory is now programmed.4.2.IO InterfaceTheHEXfileisdownloadedfromahostviathestandardC51UARTusingafull-duplexcommunicationprotocolwithaXON/XOFFdataflowcontrol.TheprogramassumesahostasasimpleterminalemulatorthatcandisplaymessagesanddownloadASCIIfiles.TheUARTroutinesimplementonecircularbufferdedicatedtothecharacterreception.AninterruptserviceroutineisinchargeofthecharacterreceptionsothatFLASHprogrammingcanoccurwhilereceivingcharactersfromthehost.•UARTReception4Rev A - 21 Jan 2000
ANM076
Uponreceptionofacharacter,theUARTinterruptroutinestoresthereceivedbyteintheRxcircularbuffer.AssoonastheISPprogramdetectstheRxbufferisnotempty,newlyreceivedcharactersarereadfromthisbufferandareprocessedbytheHEXfiledecoder.AssoonastheRxbufferisalmostfull,anXOFFcharacterisautomaticallytransmittedtoindicatetheterminalthatreceptionshallstop.WhenasufficientnumberofcharactershavebeenreadandtheRxbufferisalmostempty,anXONcharacterissenttotheterminaltoresumethetransmission.UARTTransmission
Somesimplemessagesaresenttothehostfordemonstrationpurpose.TheyaresenttotheUARTusingtheprintffunctionprovidedbytheKeilDevelopmentKit[5].ThisprintffunctionisbasedonaputcharfunctionthathandlestheXON/XOFFflowcontrol.
•
4.3.Intel HEX File Parser
TheIntelHEXfileisastandardfileformatforbinaryprogramcodeencodingusingASCIIcharacters(see[3]).Basically,theIntelHEXfilecontainsrecords.Eachrecordismadeofthefollowingitems:
••••
Recordlength:numberofbytesintherecord
Recordtype:describestheinformationcontainedintherecord(data,endoffile,segmentaddress,...)Addressfield:indicatedwherethefollowingbytesarestoredinthememoryChecksum
Tominimizethedatastoragevolume,theHEXfileparserfunctionanalysesonaperbytebasiseachrecord.TheHEXdecoderdecodeseachrecordfieldsandextractstheaddressoffsetandtheactualbytesthatneedtobeprogrammedtotheFLASHmemory.
TheparserstructureisbasedonstatemachineshowninFigure5.
SincetheHEXfiletransmittedbythehostencodeshexadecimalbyteinASCIIform,theHEXdecoderfunctionmustconvertASCIIdigitsintobinaryformatbeforeprocessing.Thisconversionismadeover2or4ASCIIdigitsaccordingtotherecordfield(addressesare4-digitnumbers,dataare2-digitnumbers).
Rev A - 21 Jan 20005
ANM076
Record MarkWait for ’:’Get recordlength 2 digits(MSB & LSB)Get AddressOffset 4 digitsGetRecordtype2 digitsCheck if still datato read in therecordGet data 2 digits&FLASHprogrammingFinal checksumcomputationChecksum ErrorChecksum OK ?Flash ProgrammedFigure5.HEXFileDecoderStateMachine4.4.FLASH ProgrammingAFLASHmemorycontrollerprovidestheuserseveralwriteanderaseoperationslikebytewrite,pagewrite,pageeraseetc...TheFLASHprogrammingsoftwareroutinesimplementedhereprovidetheerasingofthewholeFLASHmemoryarrayandthewritingofonebyte.TheFLASHmemorycontrollerhandshakingrequiredforaneraseorwriteoperationaredetailledin[4].ThetwobasicsequencesareshownFigure6andFigure7.6Rev A - 21 Jan 2000
ANM076
4.4.1.Chip EraseTheChipErasecommandconsistsofa6cyclesequence.Uponreceptionofthecommand,theFLASHmemorystartsitserasureprocess.Whileerasureprocessison-going,thebit6oftheFLASHdatabustoggleseachtimeamemorylocationisaccessed.Assoonasthisbitstopsflippingwhenaccessed,theerasingoperationisover.Erase commandWriteAAh@5555hWrite55h@2AAAhWrite 80h @ 5555hWriteAAh@5555hWrite55h@2AAAhWrite 10h @ 5555hRead @ 5555hChecks bit IO6toggles?End of Erase SequenceFigure6.FLASHEraseSequence4.4.2.Byte ProgrammingTheByteProgrammingcommandconsistsofa4cyclesequence.Uponreceptionofthecommand,theFLASHmemorywaitsforthedatawritesequenceandstartsitsprogrammingprocess.Whileprogrammingprocessison-going,thebit7oftheFLASHdatabusisinvertedeachtimethememorylocationisaccessed.AssoonasthecorrectdataisreadfromthelastprogrammedFLASHmemorylocation,theprogrammingoperationisover.Rev A - 21 Jan 20007
ANM076
Write commandWriteAAh@5555hWrite55h@2AAAhWrite A0h @ 5555hWrite data @ addrRead data @ addrBit 7 of datanegated?End of Byte ProgrammingFigure7.FLASHWriteSequence5.Bibliography[1]C51ProductDatasheets(AtmelWireless&Microcontrollers)[2]TSC80251G1DesignGuide((AtmelWireless&Microcontrollers)[3]HexdecimalObjectFileFormatSpecification(Intel)[4]AT49HF010FLASHMemoryDatasheet(Atmel)[5]KeilC51CCompilerManual6.Sites to VisitAtmelWireless&MicrocontrollersWebsite:http://www.atmel-wm.com.com8Rev A - 21 Jan 2000
ANM076
7.Appendix A: Software
7.1.MAIN.C
/*C*************************************************************************** NAME: main.c
*----------------------------------------------------------------------------* PURPOSE:
* Main entry for ISP program and system initialization.
* Main entry includes all the ISP sequence from FLASH erase to FLASH prog.
*****************************************************************************//*_____ I N C L U D E S ____________________________________________________*/#include /*F*************************************************************************** NAME: _DEAD_ *----------------------------------------------------------------------------* PURPOSE: * When a fatal error occurs, this function is called to end with a standard* error message and a never end loop. *****************************************************************************/void _DEAD_(void){ printf(\"\\nError: cannot continue!\\n\"); while (1);} /*F*************************************************************************** NAME: system_init *----------------------------------------------------------------------------* PURPOSE: * Initializes the microcontroller: XRAM disabled to enable the FLASH mapping* into the data space and uart settings. *****************************************************************************/void system_init(void){ /* Disable on-chip XRAM if exists */#ifdef HAVE_XRAM AUXR = NO_XDATA;#endif /* Initialize communication port */ uart_init(); EA = 1;} /*F*************************************************************************** NAME: main *----------------------------------------------------------------------------* PURPOSE: * Program main entry. Manages the basic ISP sequence flow from FLASH ersure* to FLASH programming. *****************************************************************************/void main(void){ Uchar status; Rev A - 21 Jan 20009 ANM076 /* System initialization: IO, welcome message, ... */ system_init(); printf(\"\\n\\n** Welcome to the ISP program! **\\n\\n\"); /* Check the Flash manufacturer and device Id (Atmel=1F, 49HF010=17) */ printf(\"Check if FLASH device is a Atmel AT49HF010... \"); if (flash_id()==0x1F17) { printf(\"OK.\\n\"); } else { printf(\"KO!\\n\"); _DEAD_(); } /* On-board FLASH erase operation */ printf(\"\\nErasing the on-board FLASH memory... \"); flash_erase(); printf(\"OK.\\n\\n\"); /* FLASH erased: ready for programming */ printf(\"Ready for FLASH programming.\\n\"); printf(\"Send .hex file with the following terminal configuration:\\n\"); printf(\" - ASCII character transmission,\\n\"); printf(\" - 8 bits, 1 stop, parity none,\\n\"), printf(\" - XON-XOFF flow control.\\n\"); printf(\"\\nWaiting for download...\\n\"); /* Parses the downloaded HEX file and program the on-board FLASH memory */ uart_rx_enable(); status = hex_parser(); uart_rx_disable(); if (status == HEX_DEC_CSERR) { printf(\"\\nChecksum error: external FLASH memory is not programmed!\\n\"); _DEAD_(); } else printf(\"\\nExternal FLASH memory is now programmed.\\n\"); /* Happy end! */ while(1);} 10Rev A - 21 Jan 2000 ANM076 7.2.IO.C /*C*************************************************************************** NAME: io.c *----------------------------------------------------------------------------* PURPOSE: * Functions dedicated to the HEX file reception from the host via the Uart.* These functions provide uart initialization, interrupt handling and* Rx circular buffer management. *****************************************************************************//*_____ I N C L U D E S ____________________________________________________*/#include \"compiler.h\"#include \"config.h\"#include \"isp.h\" /*_____ M A C R O S ________________________________________________________*//* XON / XOFF Contro characters */#define XON 17#define XOFF 19 /* Must be 2^y for modulo computation */#define RX_BUF_SIZE 16 /* XOFF when only 50% buffer size left *//* XON when 25% rx buffer full */ #define XOFF_THRESH (RX_BUF_SIZE - (RX_BUF_SIZE / 2) )#define XON_THRESH (RX_BUF_SIZE / 4)/* Wait for end of Tx over the Uart */ #define WAIT_EO_TX {while (TI==0); TI=0;} /*_____ D E F I N I T I O N ________________________________________________*/static Uchar rx_buffer[RX_BUF_SIZE]; /* Rx circular buffer */ static Uchar rx_index_wr; /* Rx circular buffer indexes */static Uchar rx_index_rd; static Bool tx_off; /* XOFF state indicator */ Uchar nb_rx_data; /* Number of data in the Rx buffer *//*_____ D E C L A R A T I O N ______________________________________________*/void rx_buffer_wr(Uchar rx_data); /*F*************************************************************************** NAME: uart *----------------------------------------------------------------------------* PURPOSE: * Uart interrupt handler: processes Rx uart events only. *****************************************************************************/Interrupt(void uart(void),4){ if (RI == 1) /* Processes Rx event only, not Tx */ { rx_buffer_wr(SBUF); /* Writes the received data into the Rx buffer */ RI = 0; }} /*F************************************************************************** Rev A - 21 Jan 200011 ANM076 * NAME: uart_tx *----------------------------------------------------------------------------* PURPOSE: * Send a character over the serial link. Exit when the character* transmission is over. *****************************************************************************/void uart_tx(Uchar tx_data){ SBUF = tx_data; WAIT_EO_TX;} /*F*************************************************************************** NAME: uart_init *----------------------------------------------------------------------------* PURPOSE: * Set the C51 Uart in 8-bit data, 9600 bauds, no parity operating mode. *****************************************************************************/void uart_init(void){ SCON = 0x50; TMOD = TMOD | 0x20 ; /* Timer1 in mode 2 & not gated */ TH1 = 0xFD; /* 9600 bauds at 11.059200 MHZ */ TL1 = 0xFD; PCON = PCON & 0X80; TCON |= 0x40; TI=1;} /*F*************************************************************************** NAME: uart_rx_enable *----------------------------------------------------------------------------* PURPOSE: * Initializes Uart for data reception: circular buffer reset, XON/XOFF* protocol initialization and interrupt enabled. *****************************************************************************/void uart_rx_enable(void){ rx_index_wr = rx_index_rd = nb_rx_data = 0; WAIT_EO_TX; /* Wait any previous transmission (printf) */ uart_tx(XON); ES = 1;} /*F*************************************************************************** NAME: uart_rx_disable *----------------------------------------------------------------------------* PURPOSE: * Disable Rx reception upon interrupts. *****************************************************************************/void uart_rx_disable(void){ ES = 0; TI = 1; /* Enable Tx for printf (polling) */} /*F************************************************************************** 12Rev A - 21 Jan 2000 ANM076 * NAME: rx_buffer_empty *----------------------------------------------------------------------------* PARAMS: * return: TRUE when Rx buffer is empty. *----------------------------------------------------------------------------* PURPOSE: * Check if new Rx data have been stored in the Rx buffer. *****************************************************************************/Bool rx_buffer_empty(void){ if (nb_rx_data == 0) return TRUE; else return FALSE;} /*F*************************************************************************** NAME: rx_buffer_wr *----------------------------------------------------------------------------* PARAMS: * rx_data: Rx data to store in the buffer. *----------------------------------------------------------------------------* PURPOSE: * Stores the newly received data in the buffer and keep indexes updated. *****************************************************************************/void rx_buffer_wr(Uchar rx_data){ nb_rx_data++; rx_buffer[rx_index_wr] = rx_data; /* Circular buffer index computation */ rx_index_wr = (rx_index_wr + 1) % RX_BUF_SIZE; /* Stops host transmission when more than XOFF_THRES characters are stored * in the Rx buffer */ if ((tx_off==FALSE) && (nb_rx_data > XOFF_THRESH)) { uart_tx(XOFF); tx_off = TRUE; }} /*F*************************************************************************** NAME: rx_buffer_rd *----------------------------------------------------------------------------* PARAMS: * return: the next data available from the Rx buffer. *----------------------------------------------------------------------------* PURPOSE: * Retrieve the next data from the RX buffer. ****************************************************************************** NOTE: * All interrupts are disabled when updating rx_data because a Rx interrupt* may occur and disturb the computation (rx_data also updated in the Uart* interrupt handler. *****************************************************************************/Uchar rx_buffer_rd(void){ static Uchar data_cnt=0; /* For progression dots */ Rev A - 21 Jan 200013 ANM076 Uchar rx_data; EA=0; /* Avoid conflicts with rx_buffer_wr() */ nb_rx_data--; EA=1; rx_data = rx_buffer[rx_index_rd]; /* Circular buffer index computation */ rx_index_rd = (rx_index_rd + 1) % RX_BUF_SIZE; /* Progression dots every 256 data */ data_cnt++; if (data_cnt == 0) uart_tx('.'); /* Resumes host transmission when less than XON_THRES characters are stored * in the Rx buffer */ EA = 0; if ((tx_off == TRUE) && (nb_rx_data < XON_THRESH)) { uart_tx(XON); tx_off = FALSE; } EA = 1; return(rx_data);} 14Rev A - 21 Jan 2000 ANM076 7.3.FLASH.C /*C*************************************************************************** NAME: flash.c *----------------------------------------------------------------------------* PURPOSE: *****************************************************************************//*_____ I N C L U D E S ____________________________________________________*/#include \"config.h\"#include \"isp.h\" /*F*************************************************************************** NAME: flash_wr *----------------------------------------------------------------------------* PARAMS: * addr: FLASH address location mapped in the external data area* val: Data value to write to the FLASH. *----------------------------------------------------------------------------* PURPOSE: * Writes a byte to the FLASH memory when located in the external data area.*****************************************************************************/void flash_wr(Uchar xdata *addr, Uchar val){ *addr = val; /* addr is a pointer to external data mem */} /*F*************************************************************************** NAME: flash_rd *----------------------------------------------------------------------------* PARAMS: * addr: FLASH address location mapped in the external data area* return: Byte value read from the FLASH memory *----------------------------------------------------------------------------* PURPOSE: * Reads a byte from the FLASH memory when located in the external data area.*****************************************************************************/Uchar flash_rd(Uchar xdata *addr){ return *addr;} /*F*************************************************************************** NAME: flash_cmd *----------------------------------------------------------------------------* PARAMS: * cmd: FLASH command used by the FLASH command sequence *----------------------------------------------------------------------------* PURPOSE: * Performs a FLASH command sequence (on-FLASH memory controller configuration)* The command is defined by the cmd code (erase, chip-id access, ...) *****************************************************************************/void flash_cmd(Uchar cmd){ flash_wr(0x5555, 0xAA); flash_wr(0x2AAA, 0x55); flash_wr(0x5555, cmd);} Rev A - 21 Jan 200015 ANM076 /*F*************************************************************************** NAME: flash_erase *----------------------------------------------------------------------------* PURPOSE: * Erases the entire FLASH memory. *****************************************************************************/void flash_erase(void){ Uchar pol_n, pol_n_1; /* Erase command sequence */ flash_cmd(0x80); flash_cmd(0x10); /* Toggle bit algorithm: IO6 toggles each time a data read occurs */ /* End of toggoling signals end of erase */ pol_n_1 = flash_rd(0x5555); pol_n = flash_rd(0x5555); while ((pol_n ^ pol_n_1) == 0x40) /* Checks if bit6 has changed between 2 polls */ { pol_n_1 = pol_n; pol_n = flash_rd(0x5555); }} /*F*************************************************************************** NAME: flash_prog *----------------------------------------------------------------------------* PARAMS: * addr: FLASH address location mapped in the external data area* val: Data value to program to the FLASH. *----------------------------------------------------------------------------* PURPOSE: * Programs one byte to the FLASH memory. *****************************************************************************/void flash_prog(Uint16 addr, Uchar value){ /* Programming command */ flash_cmd(0xA0); flash_wr(addr, value); /* Wait until end of programming: IO7 is negated until end of programming */ while (flash_rd(addr) != value);} /*F*************************************************************************** NAME: flash_id *----------------------------------------------------------------------------* PARAMS: * return: FLASH memory manufacturer id and device id bytes.* MSB is Manufacturer Id and LSB Device Id. *----------------------------------------------------------------------------* PURPOSE: * Read the manufactuer and device Id's. *****************************************************************************/Uint16 flash_id() 16Rev A - 21 Jan 2000 ANM076 { Uint16 flash_id=0; /* Product Id Entry mode */ flash_cmd(0x90); /* @0000: manufacturer, @0001: device */ flash_id = flash_rd(0x0000) << 8 | flash_rd(0x0001); /* Exit from Product Id */ flash_cmd(0xF0); return flash_id;} Rev A - 21 Jan 200017 ANM076 7.4.HEX.C /*C*************************************************************************** NAME: hex.c *----------------------------------------------------------------------------* PURPOSE: * HEX file decoder: extracts HEX file information, retrieve data and program* the FLASH memory on the fly. *****************************************************************************//*_____ I N C L U D E S ____________________________________________________*/#include \"config.h\"#include \"isp.h\"#include /*_____ M A C R O S ________________________________________________________*//* State definition of the HEX file decoder state machine */#define REC_MARK 0x01#define REC_LEN_1 0x02#define REC_LEN_2 0x03#define OFFSET_1 0x04#define OFFSET_2 0x05#define OFFSET_3 0x06#define OFFSET_4 0x07#define REC_TYP_1 0x08#define REC_TYP_2 0x09#define DATA_1 0x0A#define DATA_2 0x0B#define CHEKSUM_1 0x0C#define CHEKSUM_2 0x0D /*_____ D E C L A R A T I O N ______________________________________________*/Uchar hex_decoder(Uchar hex_data); /*F*************************************************************************** NAME: hex_parser *----------------------------------------------------------------------------* PARAMS: * return: Exit status of the HEX file parser: OK or bad CRC encountered. *----------------------------------------------------------------------------* PURPOSE: * Monitors the HEX file Rx buffer and call the HEX decoder as soon as data* are available. *****************************************************************************/Uchar hex_parser(void){ Uchar hex_data, status; status = HEX_DEC_OK; while (status == HEX_DEC_OK) /* Processes while hex decoder status is OK */ { if(nb_rx_data != 0) { hex_data = rx_buffer_rd(); status = hex_decoder(hex_data); } } return status; 18Rev A - 21 Jan 2000 ANM076 } /*F*************************************************************************** NAME: hex_decoder *----------------------------------------------------------------------------* PARAMS: * hex_data: data from the HEX file to decode * return: Hex decoder exit status: OK or bad CRC encountered. *----------------------------------------------------------------------------* PURPOSE: * Decodes all HEX file records on a byte per byte basis: analyse HEX record,* extracts data for FLASH programming and verifies the checksum. ****************************************************************************** NOTE: * HEX data are ASCII data format. Each byte is made of 2 ASCII form digits* that needed to be converted. Conversion uses toint which is not a ANSI* C function. One should use strtol when available (not in Keil C lib). *****************************************************************************/Uchar hex_decoder(Uchar hex_data){ static state = REC_MARK; static Uchar length, type, nb_byte, data_value, sum, sum_1, sum_2; static Uint16 offset; Uchar status; status = HEX_DEC_OK; switch(state) { case REC_MARK: /* Start of a new record */ { if (hex_data == ':') /* Check if the right character */ { state = REC_LEN_1; /* If ok, next step: get the 1st lenght char */ nb_byte=0; } else state = REC_MARK; /* If ko, spurious char and skip */ break; } case REC_LEN_1: /* Get the 1st digit of the length byte */ { length = toint(hex_data) * 16; state = REC_LEN_2; break; } case REC_LEN_2: /* Get the 2nd digit of the lenght byte */ { length = length + toint(hex_data); state = OFFSET_1; break; } case OFFSET_1: /* Get the 1st digit of the adress byte */ { offset = toint(hex_data) * 4096; Rev A - 21 Jan 200019 ANM076 state = OFFSET_2; break; } case OFFSET_2: /* Get the 2nd digit of the adress byte */ { offset = offset + toint(hex_data) * 256; sum_1= offset / 256; state = OFFSET_3; break; } case OFFSET_3: /* Get the 3rd digit of the adress byte */ { offset = offset + toint(hex_data) * 16; state = OFFSET_4; break; } case OFFSET_4: /* Get the 4th digit of the adress byte */ { offset = offset + toint(hex_data); sum_2 = offset - sum_1 * 256; state = REC_TYP_1; break; } case REC_TYP_1: /* Get the 1st digit of the record type */ { type = toint(hex_data) * 16; state =REC_TYP_2; break; } case REC_TYP_2: /* Get the 2nd digit of the record type */ { type = type + toint(hex_data); sum = length + sum_1 + sum_2 + type; if (length==0x00) state=CHEKSUM_1; /* If no data, go to checksum computation */ else state = DATA_1; /* Otherwise next is data record acquisition */ break; } case DATA_1: /* Get the 1st digit of one data */ { data_value = toint(hex_data) * 16 ; state = DATA_2; break; } case DATA_2: /* Get the 2nd digit of one data */ { data_value = data_value + toint(hex_data); sum = sum + data_value; flash_prog(offset + nb_byte, data_value); 20Rev A - 21 Jan 2000 ANM076 nb_byte++; if (nb_byte == length) state = CHEKSUM_1; /* If end of data block, go to checksum */ else state = DATA_1; /* Otherwise, get the next data in the block */ break; } case CHEKSUM_1: /* Get 1st digit of the checksum */ { sum_1 = toint(hex_data) * 16; sum = (~sum) + 1; /* Checksum 2 complement */ state = CHEKSUM_2; break; } case CHEKSUM_2: /* Get 2nd digit of the checksum */ { sum_1 = sum_1 + toint(hex_data); if (sum_1 != sum) status = HEX_DEC_CSERR; state = REC_MARK; /* Ready for next record */ if(type==0x01) status = HEX_DEC_END; /* end of transmission */ break; } } return status;} Rev A - 21 Jan 200021 ANM076 7.5.CONFIG.H /*H**************************************************************************** NAME: myfile.h *----------------------------------------------------------------------------* PURPOSE: *****************************************************************************/#ifndef _CONFIG_H_#define _CONFIG_H_ /*_____ I N C L U D E S ____________________________________________________*/#include /* ______________________ User Configuration Section ______________________ */#define HAVE_XRAM /* Target chip: T89C51RD2 with on-chip XRAM *//* ______________________ User Configuration Section ______________________ */ #ifdef HAVE_XRAM /* If on-chip XRAM, disable the XRAM to access to theentire */ #define NO_XDATA 0x02 /* FLASH when mapped in the data area */Sfr (AUXR, 0x8E);#endif #endif /* _CONFIG_H_ */ 22Rev A - 21 Jan 2000 ANM076 7.6.COMPILER.H /*H**************************************************************************** NAME: compiler.h *----------------------------------------------------------------------------* PURPOSE: * Defines compiler dependant definitions to enhance program portability. * Allows to remap exotic syntaxes to another exotic syntaxe without changing* C source files. *****************************************************************************/#ifndef _COMPILER_H_#define _COMPILER_H_ /*_____ M A C R O S ________________________________________________________*/#define FALSE 0#define TRUE 1 /*_____ D E F I N I T I O N ________________________________________________*/typedef unsigned char Uchar;typedef unsigned short Uint16;typedef signed int Int16;typedef float Float16;typedef unsigned char Bool; /* KEIL compiler syntax redefinition */#define Reentrant(x) x reentrant#define Sfr(x,y) sfr x = y #define Sbit(x,y,z) sbit x = y ^ z#define Interrupt(x,y) x interrupt y#define At(x) _at_ x#endif /* _COMPILER_H_ */ Rev A - 21 Jan 200023 ANM076 7.7.ISP.H /*H**************************************************************************** NAME: isp.h *----------------------------------------------------------------------------* PURPOSE: Header file shared by all ISP C files. *****************************************************************************/#ifndef _ISP_H_#define _ISP_H_ /* Uart */ extern Uchar nb_rx_data;void uart_init(void); void uart_rx_enable(void);void uart_rx_disable(void);Bool rx_buffer_empty(void);Uchar rx_buffer_rd(void);/* HEX file parser */ #define HEX_DEC_OK 0x01#define HEX_DEC_END 0x02#define HEX_DEC_CSERR 0x03Uchar hex_parser (void); /* FLASH API's*/ void flash_erase(void); void flash_prog(Uint16, Uchar value);Uint16 flash_id(void);#endif /* _ISP_H_ */ 24Rev A - 21 Jan 2000 因篇幅问题不能全部显示,请点此查看更多更全内容