;*************************************************************************** ;* ;* Title : AVR ISP (Auto adr inc, 19200bps) ;* Version : 2.2 ;* Last updated : May 31 2000 (pkastnes) ;* Target : AT90S1200 ;* File : avr910.asm ;* Author(s) : Ole Saether, Terje Frostad, ;* Ingar Fredriksen, Morten W. Lund ;* Haakon Skar, Paal Kastnes ;* ;* DESCRIPTION ;* The firmware On All programmers now support a unified protocol For ;* program And Data memory programming. The host computer Do Not need ;* To know If the programmer operates in serial Or parallel mode. ;* ;* The following commands are supported. All commands Start with a ;* single letter. The programmer returns 13d (carriage Return) Or the ;* Data read after the command is finished. ;* ;* +-------------+------------+------+ ;* Commands | Host writes | Host reads | | ;* -------- +-----+-------+------+-----+ | ;* | ID | Data | Data | | Note | ;* +-----------------------------------+-----+-------+------+-----+------+ ;* | Enter programming mode | 'P' | | | 13d | 1 | ;* | Report autoincrement address | 'a' | | | 'Y' | | ;* | Set address | 'A' | ah al | | 13d | 2 | ;* | Write program memory, Low Byte | 'c' | dd | | 13d | 3 | ;* | Write program memory, high Byte | 'C' | dd | | 13d | 3 | ;* | Issue Page Write | 'm' | | | 13d | | ;* | Read program memory | 'R' | |dd(dd)| | 4 | ;* | Write Data memory | 'D' | dd | | 13d | | ;* | Read Data memory | 'd' | | dd | | | ;* | Chip erase | 'e' | | | 13d | | ;* | Write lock bits | 'l' | dd | | 13d | | ;* | Write fuse bits | 'f' | dd | | 13d | 11 | ;* | Read fuse And lock bits | 'F' | | dd | | 11 | ;* | Leave programming mode | 'L' | | | 13d | 5 | ;* | Select device type | 'T' | dd | | 13d | 6 | ;* | Read signature bytes | 's' | | 3*dd | | | ;* | Return supported device codes | 't' | | n*dd | 00d | 7 | ;* | Return software identifier | 'S' | | s[7] | | 8 | ;* | Return sofware version | 'V' | |dd dd | | 9 | ;* | Return hardware version | 'v' | |dd dd | | 9 | ;* | Return programmer type | 'p' | | dd | | 10 | ;* | Set LED | 'x' | dd | | 13d | 12 | ;* | Clear LED | 'y' | dd | | 13d | 12 | ;* | Universial command | ':' | 3*dd | dd | 13d | | ;* | New universal command | '.' | 4*dd | dd | 13d | | ;* | Special test command | 'Z' | 2*dd | dd | | | ;* +-----------------------------------+-----+-------+------+-----+------+ ;* ;* NOTE 1 ;* The Enter programming mode command MUST be sent one time prior To ;* the other commands, with the exception of the 't', 'S', 'V', 'v' ;* And 'T' commands. The 'T' command must be sent before this command ;* (see note 6). ;* ;* For programmers supporting both parallel And serial programming ;* mode this command enters parallel programming mode. For programmers ;* supporting only serial programming mode, this command enters serial ;* programming mode. ;* ;* NOTE 2 ;* The ah And al are the high And Low order bytes of the address. For ;* parallel programmers this command issues the Load Address Low/High ;* Byte command. For serial programmers the address Byte is stored For ;* use by the Read/Write commands. ;* ;* NOTE 3 ;* For parallel programmers this command issues the Program Flash ;* command. For serial programmers this command iussues the Write ;* Program Memory Command. For devices with Byte-wide program memories ;* only the Low Byte command should be used. ;* ;* NOTE 4 ;* The contents of the program memory At the address given by the 'A' ;* command are written To the serial port in binary form. For Byte ;* wide memories one Byte is written. For 16 Bit memories two bytes ;* are written,Msb first. ;* ;* NOTE 5 ;* This command must be executed after the programming is finished. ;* ;* NOTE 6 ;* The Select device type command must be sent before the enter ;* programming command ;* ;* NOTE 7 ;* The supported device codes are returned in binary form terminated ;* by 0x00. ;* ;* NOTE 8 ;* This Return a 7 character ASCII String identifying the programmer. ;* For the development board it is "AVR DEV", For the parallel ;* programmer it is "AVR PPR" And For the in-curcuit programmer it is ;* "AVR ICP". ;* ;* NOTE 9 ;* The software/hardware version are returned As two ASCII numbers. ;* ;* NOTE 10 ;* This command should be used To identify the programmer type. The ;* Return value is 'S' for serial (or SPI) programmers or 'P' for ;* parallel programmers. ;* ;* NOTE 11 ;* The write fuse bits command are available only On parallel ;* programmers And only For AVR devices (device code < 0x80). The host ;* should use the Return programmer type command To determine the ;* programmer type, Do Not use the "AVR PPR" idenifier because other ;* programmers may be available in the future. ;* ;* NOTE 12 ;* Currently only the AVR development board has LEDs. The other boards ;* must implement this commands As NOPs. ;* ;* NOTE 13 ;* Devices using Page Mode Programming write one page of Flash memory ;* before issuing a Page Mode Write Pulse. ;* ;* HISTORY ;* V2.2 00.03.10 (pkastnes) Added support For multiple new devices ;* V2.1 98.10.26 (mlund) New date marking. ;* Removed support For AT90S1200C. ;* Added support For AT90S4433A. ;* V2.0 98.01.06 (mlund) ATmega103 support ;* V1.7 97.11.06 (mlund) Universial command (':') implemented. ;* Releases All pins when Not in ;* programming mode. ;* V1.6e 97.11.04 (mlund) mega103 rev D support ;* V1.6c 97.10.30 (mlund) Auto incrementing / Spi sync ;* also works For mega103. ;* V1.6 97.09.09 (hskar) Created Page Mode Version (mega103) ;* V1.5 97.08.21 (mlund) Modified / Bugfix / Major cleanup ;* ... ... (no records) ;* V?.? 97.03.15 (OS) Created ;* ;* ;* ;* Device Support List ;* ------------------- ;* ;* +-------+----------+------+-------+------+------+------+-------+ ;* |Device |Signature | Code | Flash |EEProm| Lock | Fuse | PMode | ;* +-------+----------+------+-------+------+------+------+-------+ ;* |tiny12 | 1E 90 05 | 0x55 | R/W | R/W | R/W | R/W | Byte | ;* |tiny15 | 1E 90 06 | 0x56 | R/W | R/W | R/W | R/W | Byte | ;* | | | | | | | | | ;* | S1200 | 1E 90 01 | 0x13 | R/W | R/W | W | NA | Byte | ;* | | | | | | | | | ;* | S2313 | 1E 91 01 | 0x20 | R/W | R/W | W | NA | Byte | ;* | S2323 | 1E 91 02 | 0x48 | R/W | R/W | R/W | R/W | Byte | ;* | S2333 | 1E 91 05 | 0x34 | R/W | R/W | R/W | R/W | Byte | ;* | S2343 | 1E 91 03 | 0x4C | R/W | R/W | R/W | R/W | Byte | ;* | | | | | | | | | ;* | S4414 | 1E 92 01 | 0x28 | R/W | R/W | W | NA | Byte | ;* | S4433 | 1E 92 03 | 0x30 | R/W | R/W | R/W | R/W | Byte | ;* | S4434 | 1E 92 02 | 0x6C | R/W | R/W | R/W | R/W | Byte | ;* | | | | | | | | | ;* | S8515 | 1E 93 01 | 0x38 | R/W | R/W | W | NA | Byte | ;* | S8535 | 1E 93 03 | 0x68 | R/W | R/W | R/W | R/W | Byte | ;* | | | | | | | | | ;* |mega83 | 1E 93 05 | 0x65 | R/W | R/W | R/W | R/W | Page | ;* |mega103| 1E 97 01 | 0x41 | R/W | R/W | R/W | R/W | Page | ;* |mega161| 1E 94 01 | 0x60 | R/W | R/W | R/W | R/W | Page | ;* |mega163| 1E 94 02 | 0x64 | R/W | R/W | R/W | R/W | Page | ;* +-------+----------+------+-------+------+------+------+-------+ ;* ;* LEGEND: ;* ------- ;* Signature - Device Signature Byte ;* Code - Unique device code used by AVRProg To identify device ;* Flash - Flash size in bytes ;* EEProm - EEProm size in bytes ;* Lock - Lockbits ;* Fuse - Fusebits ;* PMode - Indicates If device uses Byte Or page programming mode ;* ;* R/W - Read And Write Access ;* R - Read Access Only ;* W - Write Access Only ;* NA - Not Accessible ;* ;*************************************************************************** ;**** includes **** .include "1200def.inc" ;*************************************************************************** ;* ;* CONSTANTS ;* device codes ;* ;* DESCRIPTION ;* The following device codes must be used by the host computer. Note ;* that the device codes are arbitrary selected, they Do Not have any ;* thing in common with the signature bytes stored in the device. ;* ;*************************************************************************** .equ tn12 = 0x55 .equ tn15 = 0x56 .equ S1200D = 0x13 .equ S2313A = 0x20 .equ S4414A = 0x28 .equ S8515A = 0x38 .equ S2323A = 0x48 .equ S2343A = 0x4C .equ S2333A = 0x34 .equ S4433A = 0x30 .equ S4434 = 0x6C .equ S8535 = 0x68 .equ m83 = 0x65 .equ m161 = 0x60 .equ m163 = 0x64 .equ m603 = 0x42 .equ m103 = 0x41 .equ m8 = 0x76 ;ATmega8 .equ m8b = 0x77 ;ATmega8 boot ;**** Revision Codes **** .equ SW_MAJOR = '2' ; Major SW revision number .equ SW_MINOR = '2' ; Minor SW revision number .equ HW_MAJOR = '1' ; Major HW revision number .equ HW_MINOR = '0' ; Minor HW revision number ;*************************************************************************** ;* ;* MACROS ;* Program Macros ;* ;* DESCRIPTION ;* Change the following four macros If the Reset pin To the ;* target moves And/Or If the SCK/MISO/MOSO moves. ;* ;*************************************************************************** .equ resetpin = 4 .macro set_reset sbi PORTB,resetpin .endm .macro clr_reset cbi PORTB,resetpin .endm .macro ddrd_init Nop ; sbi DDRD,3 .endm .macro ddrb_init ldi temp1,(0xFF ^ (1<= 0x20) && (device <= 0x7F) ) brlo s2 tst device brmi s2 s0b: ; { ldi count,32 ; count = 32; s1: ; Do { rcall rdser ; If (rdser == 0x53) // Spi read (Byte 3) cpi s_data,0x53 breq s3 ; break; ldi s_data,0x00 ; wrser(0x00); // Spi write (Byte 4) rcall wrser pulse_sck ; Pulse SCK ldi s_data,0xac ; wrser(0xac); // Spi write (Byte 1) rcall wrser ldi s_data,0x53 ; wrser(0x53); // Spi write (Byte 2) rcall wrser dec count ; } While(--count); brne s1 rjmp s3 ; } ; Else s2: ; { ldi s_data,0x00 ; wrser(0x00); // Spi write (Byte 3) rcall wrser s3: ; } ldi s_data,0x00 ; wrser(0x00); // Spi write (Byte 4) rcall wrser ldi temp1,0x10 ; delay(0x10); rcall delay ret ;*************************************************************************** ;* ;* Function ;* show_id ;* ;* DESCRIPTION ;* Show our ID ("AVR ISP") On the serial Line. ;* ;*************************************************************************** show_id: ldi u_data,0x41 ; 'A' rcall putc ldi u_data,0x56 ; 'V' rcall putc ldi u_data,0x52 ; 'R' rcall putc ldi u_data,0x20 ; ' ' rcall putc ldi u_data,0x49 ; 'I' rcall putc ldi u_data,0x53 ; 'S' rcall putc ldi u_data,0x50 ; 'P' rcall putc ret ;*************************************************************************** ;* ;* Reset ;* ;* DESCRIPTION ;* Initialization ;* ;*************************************************************************** Reset: clr temp1 out GIMSK,temp1 ; Disable external Interrupt ser temp1 ; Initialize out PORTD,temp1 set_reset ; Set Reset=1 out PORTB,temp1 ddrb_release rcall u_init ; Initialize UART sei ; Enable Interrupts ;*************************************************************************** ;* ;* PROGRAM ;* waitcmd -> main ;* ;* DESCRIPTION ;* Wait For And execute commands. ;* ;*************************************************************************** waitcmd: rcall getc ; While (getc() == ESC) {}; cpi u_data,0x1b breq waitcmd ;**** Device Type **** cpi u_data,0x54 ; 'T' Device type brne w0 rcall getc ; getc(); // dummy mov device,u_data ; putc(device); rjmp put_ret ;**** Return Software Identifier **** w0: cpi u_data,0x53 ; 'S' Return software identifier brne w1 rcall show_id ; show_id(); rjmp waitcmd ;**** Return Software Version **** w1: cpi u_data,0x56 ;'V' Return software version brne w2 ldi u_data,SW_MAJOR rcall putc ldi u_data,SW_MINOR rcall putc rjmp waitcmd ;**** Return Hardware Version **** w2: cpi u_data,0x76 ;'v' Return hardware version brne w3 ldi u_data,0x30+HW_MAJOR ; putc(0x30+HW_MAJOR); rcall putc ldi u_data,0x30+HW_MINOR ; putc(0x30+HW_MINOR); rcall putc rjmp waitcmd ;**** Show Supported Devices **** w3: cpi u_data,0x74 ; 't' Show supported devices brne w4 ldi u_data,tn12 ; putc(tiny12); rcall putc ldi u_data,tn15 ; putc(tiny15); rcall putc ldi u_data,S1200D ; putc(S1200D); rcall putc ldi u_data,S2313A ; putc(S2313A); rcall putc ldi u_data,S4414A ; putc(S4414A); rcall putc ldi u_data,S8515A ; putc(S8515A); rcall putc ldi u_data,S2323A ; putc(S2323A); rcall putc ldi u_data,S2343A ; putc(S2343A); rcall putc ldi u_data,S2333A ; putc(S2333A); rcall putc ldi u_data,S4433A ; putc(S4433A); rcall putc ldi u_data,S4434 ; putc(S4434); rcall putc ldi u_data,S8535 ; putc(S8535); rcall putc ldi u_data,m83 ; putc(m83); rcall putc ldi u_data,m161 ; putc(mega161); rcall putc ldi u_data,m163 ; putc(mega163); rcall putc ldi u_data,m103 ; putc(mega103); rcall putc ldi u_data,m603 ; putc(mega603); rcall putc ldi u_data,m8 ; putc (mega8); rcall putc ldi u_data,m8b ; putc (mega8 BOOT); rcall putc ldi u_data,0x00 ; putc(0x00); // End of device list rcall putc rjmp waitcmd ;**** Return Programmer Type **** w4: cpi u_data,0x70 ; 'p' Return programmer type brne w51 ldi u_data,0x53 ; putc('S'); // serial programmer rcall putc rjmp waitcmd ;**** Return autoincrement address support w51: cpi u_data,'a' ; 'a' Return address auto increment brne w5 ldi u_data,'Y' ; putc('Y'); // supports autoinc rcall putc rjmp waitcmd ;**** Set LED **** w5: cpi u_data,0x78 ; 'x' Set LED (ignored) brne w6 rjmp put_ret ;**** Clear LED **** w6: cpi u_data,0x79 ; 'y' Clear LED (ignored) brne w7 rjmp put_ret ;**** Enter Programming Mode **** ; We require that the device code be selected before any of the other commands w7: cpi device,tn12 ; If ((device != tn12) && breq w72 cpi device,tn15 ; If ((device != tn15) && breq w72 cpi device,S1200D ; If ((device != S1200D) && breq w72 cpi device,S2313A ; (device != S2313A) && breq w72 cpi device,S4414A ; (device != S4414A) && breq w72 cpi device,S8515A ; (device != S8515A) && breq w72 cpi device,S2323A ; (device != S2323A)) breq w72 cpi device,S2343A ; (device != S2343A)) breq w72 cpi device,S2333A ; (device != S2333A) && breq w72 cpi device,S4433A ; (device != S4433A) && breq w72 cpi device,S4434 ; (device != S4434A) && breq w72 cpi device,S8535 ; (device != S8535) && breq w72 cpi device,m83 ; (device != m83) && breq w72 cpi device,m161 ; (device != m161) && breq w72 cpi device,m163 ; (device != m163) && breq w72 cpi device,m603 ; (device != m603) && breq w72 cpi device,m103 ; (device != m103) && cpi device,m8 ; (device != m8) && breq w72 cpi device,m8b ; (device != m8 BOOT) && breq w72 rjmp put_err ; GoTo put_err(); w72: cpi u_data,0x50 ; 'P' Enter programming mode brne w8 rcall spiinit ; spiinit(); rjmp put_ret ;**** Wait Program Memory **** ;* USAGE ;* wait_pm(Byte cmd, Byte c_data); ;* ;* cmd : 0x28 - Wait For high Byte written ;* 0x20 - Wait For Low Byte written ;* u_data : current Data written ;wait_pm: ; Do ; ; { ; mov s_data,cmd ; wrser(cmd); // Spi write (Byte 1) ; rcall wrser ; mov s_data,addrh ; wrser(addrh); // Spi write (Byte 2) ; rcall wrser ; mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) ; rcall wrser ; rcall rdser ; s_data = rdser(); // Spi read (Byte 4) ; } ; cp s_data,u_data ; While(s_data != u_data); ; brne wait_pm ; ret ;**** Write Program Memory, High Byte **** w8: cpi u_data,0x43 ; 'C' Write program memory, high byte brne w9 rcall getc w81: ldi s_data,0x48 ; wrser(0x48); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; wrser(addrh); // Spi write (Byte 2) rcall wrser mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser mov s_data,u_data ; wrser(u_data); // Spi write (Byte 4) rcall wrser ldi temp1,0x01 ; Auto increment address !!!! clr temp2 add addrl,temp1 Adc addrh,temp2 rjmp writeFLASHdelay ;**** Write Program Memory, Low Byte **** w9: cpi u_data,0x63 ; 'c' Write program memory, low byte brne w12 rcall getc ldi s_data,0x40 ; wrser(0x40); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; s_data = addrh; w91: ; } rcall wrser ; wrser(s_data); // Spi write (Byte 2) mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser mov s_data,u_data ; wrser(u_data); // Spi write (Byte 4) rcall wrser writeFLASHdelay: cpi device,m103 breq w92 cpi device,m83 breq w92 cpi device,m603 breq w92 cpi device,m161 breq w92 cpi device,m163 breq w92 cpi device,m8 breq w92 cpi device,m8b breq w92 ldi temp1,0x20 ; delay(0x20); // 24585 cycles delay rcall delay ; // Page mode requires no delay! w92: rjmp put_ret ; GoTo reply(); ;**** Read Program Memory **** w12: cpi u_data,0x52 ; 'R' Read program memory brne w10 ; ldi s_data,0x28 ; wrser(0x28); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; s_data = addrh; rcall wrser ; wrser(s_data); // Spi write (Byte 2) mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser rcall rdser ; putc(rdser()); // Send Data (Byte 4) mov u_data,s_data rcall putc ldi s_data,0x20 ; wrser(0x20); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; wrser(addrh); // Spi write (Byte 2) rcall wrser mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser rcall rdser ; putc(rdser()); // Send Data (Byte 4) mov u_data,s_data rcall putc rjmp readaddrinc ;**** Load Address **** w10: cpi u_data,0x41 ; 'A' Load address brne w11 rcall getc ; addrh = getc(); mov addrh,u_data rcall getc ; addrl = getc(); mov addrl,u_data rjmp put_ret ; GoTo reply(); ;**** Write Data Memory **** w11: cpi u_data,0x44 ; 'D' Write data memory brne w13 rcall getc ldi s_data,0xc0 rcall wrser mov s_data,addrh rcall wrser mov s_data,addrl rcall wrser mov s_data,u_data rcall wrser ldi temp1,0x20 rcall delay ldi temp1,0x01 ; Auto increment address !!!! clr temp2 add addrl,temp1 Adc addrh,temp2 rjmp put_ret ;;**** Read Data Memory **** w13: cpi u_data,0x64 ; 'd' Read data memory brne w14 ldi s_data,0xa0 ; wrser(0xA0); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; s_data = addrh; rcall wrser ; wrser(s_data); // Spi write (Byte 2) mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser rcall rdser ; putc(rdser()); // Send Data (Byte 4) mov u_data,s_data rcall putc readaddrinc: ldi temp1,0x01 ; Auto increment address !!!! clr temp2 add addrl,temp1 Adc addrh,temp2 rjmp waitcmd ; GoTo waitcmd(); ;**** Leave Programming Mode **** w14: cpi u_data,0x4c ; 'L' Leave programming mode brne w15 ddrb_release set_reset ; Set Reset = 1 rjmp put_ret ;**** Chip Erase **** w15: cpi u_data,0x65 ; 'e' Chip erase brne w16 ldi s_data,0xac rcall wrser ldi s_data,0x80 rcall wrser ldi s_data,0x04 rcall wrser ldi s_data,0x00 rcall wrser ldi temp1,0x30 rcall delay rjmp put_ret ;**** Write Lock Bits **** w16: cpi u_data,0x6c ; 'l' Write lock bits brne w17 rcall getc ldi s_data,0xac rcall wrser mov s_data,u_data andi s_data,0x06 ori s_data,0xe0 rcall wrser ldi s_data,0x00 rcall wrser w162: ldi s_data,0x00 rcall wrser ldi temp1,0x30 rcall delay rjmp put_ret ;**** Read Signature Bytes **** w17: cpi u_data,0x73 ; 's' Read signature bytes brne w18 ldi param1,0x02 rcall w17call ldi param1,0x01 rcall w17call ldi param1,0x00 rcall w17call rjmp waitcmd w17call: ldi s_data,0x30 rcall wrser ldi s_data,0x00 rcall wrser mov s_data,param1 rcall wrser rcall rdser mov u_data,s_data rcall putc ret ;**** Write Program Memory Page **** w18: cpi u_data,0x6D ; 'm' Write Program Memory Page brne w19 ldi s_data,0x4c ; wrser(0x4c); // Spi write (Byte 1) rcall wrser mov s_data,addrh ; wrser(addrh); // Spi write (Byte 2) rcall wrser mov s_data,addrl ; wrser(addrl); // Spi write (Byte 3) rcall wrser ldi s_data,0x00 ; wrser(0x00); // Spi write (Byte 4) rcall wrser ldi temp1,0xff ; delay(0xFF); // 0x20 = 24585 cycles delay rcall delay rjmp put_ret ;**** Universal Command **** w19: cpi u_data,0x3A ; ':' Universal Command brne w191 rcall getc mov cmd1,u_data rcall getc mov cmd2,u_data rcall getc mov cmd3,u_data clr u_data rcall NewUniversal ldi temp1,0xff ; delay(0xFF); // 0x20 = 24585 cycles delay rcall delay rjmp put_ret ;**** New Universal Command **** w191: cpi u_data,'.' ; '.' New Universal Command brne w99 rcall getc mov cmd1,u_data rcall getc mov cmd2,u_data rcall getc mov cmd3,u_data rcall getc rcall NewUniversal ldi temp1,0xff ; delay(0xFF); // 0x20 = 24585 cycles delay rcall delay rjmp put_ret NewUniversal: mov s_data,cmd1 rcall wrser mov s_data,cmd2 rcall wrser mov s_data,cmd3 rcall wrser mov s_data,u_data rcall wrser mov u_data,rd_s_data rcall putc ret w99: ;**** Command Error **** put_err: ldi u_data,0x3f ; putc('?'); \\ send '?' rcall putc rjmp waitcmd ;**** Reply Command **** put_ret: ldi u_data,0x0d ; putc(0x0D); \\ send CR rcall putc rjmp waitcmd delay1us: ; count R16 Nop cpi temp1,0x03 breq finished Nop Nop Loop: dec temp1 cpi temp1,0x03 brne Loop finished: ret ;**** End of File ****