| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164 |
- ;
- ; Copyright (C) 2002-2003 by egnite Software GmbH. All rights reserved.
- ;
- ; Redistribution and use in source and binary forms, with or without
- ; modification, are permitted provided that the following conditions
- ; are met:
- ;
- ; 1. Redistributions of source code must retain the above copyright
- ; notice, this list of conditions and the following disclaimer.
- ; 2. Redistributions in binary form must reproduce the above copyright
- ; notice, this list of conditions and the following disclaimer in the
- ; documentation and/or other materials provided with the distribution.
- ; 3. All advertising materials mentioning features or use of this
- ; software must display the following acknowledgement:
- ;
- ; This product includes software developed by egnite Software GmbH
- ; and its contributors.
- ;
- ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ; ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- ; FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- ; COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- ; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- ; OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- ; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- ; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- ; THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- ; SUCH DAMAGE.
- ;
- ; For additional information see http://www.ethernut.de/
- ;
- ; $Log$
- ; Revision 1.1 2003/11/03 15:51:31 haraldkipp
- ; First check in
- ;
- ;
- .nolist
- #include "avr/io.h"
- .list
- ; This program implements a minimalist STK500 compatible programming
- ; adapter for the serial port on an AT90S2313 MCU. It had been
- ; originally written for AVR Studio, but then ported to AVR-GCC and
- ; will no longer build with AVR Studio. However, the resulting
- ; programmer had been successfully tested with AVR Studio 4.07 and
- ; uisp version 20030827cvs on ATmega128 and ATmega13 targets.
- ;
- ; *********************************************************************
- ; Protocol definitions
- ; Initially the STK500 protocol had been evaluated by re-engineering.
- ; Some months later Atmel decided to publish it. See
- ; http://www.atmel.com/atmel/acrobat/doc2525.pdf
- #define STK_OK 0x10
- #define STK_INSYNC 0x14
- #define STK_NOSYNC 0x15
- #define CRC_EOP 0x20
- ; *********************************************************************
- ; General configurations
- ; Baudrate factor. AVR Studio uses a fixed rate of 115,200 Baud, which
- ; results in a baudrate register factor of 1 on a 3.6864 MHz MCU. See
- ; the AT90S2313 datasheet for further details.
- #define BRFACTOR 1
- ; *********************************************************************
- ; Port Usage
- ; PB0: Unused
- ; PB1: Unused
- ; PB2: ISP-LED (out)
- ; PB3: LED (out)
- ; PB4: ISP-RESET (out)
- ; PB5: ISP-MOSI (out)
- ; PB6: ISP-MISO (in)
- ; PB7: ISP-SCK (out)
- ;
- ; PD0: RXD (in)
- ; PD1: TXD (out)
- ; PD2: HSIN/INT0 (in)
- ; PD3: HSOUT (out)
- ; PD4: unused
- ; PD5: unused
- ; PD6: unused
- ;
- #define ISPLED 2
- #define LEDIND 3
- #define ISPRST 4
- #define ISPMOSI 5
- #define ISPMISO 6
- #define ISPSCK 7
- #define HSIN 2
- #define HSOUT 3
- ; *********************************************************************
- ; Register usage
- #define r_temp r16
- #define r_data r17
- #define r_isp r18
- #define r_shift r19
- #define r_delay r20
- #define r_retry r21
- #define r_size r22
- #define r_parm r23
- ; *********************************************************************
- ; RAM variables
- .section .bss
- paddrl: .space 1
- paddrh: .space 1
- unicmd1: .space 1
- unicmd2: .space 1
- unicmd3: .space 1
- unicmd4: .space 1
- pm_devicecode: .space 1 ; device code
- pm_revision: .space 1 ; device revision
- pm_progtype: .space 1 ; "0" both, "1" par only
- pm_parmode: .space 1 ; "0" pseudo, "1" full
- pm_polling: .space 1 ; "0" no, "1" yes
- pm_selftimed: .space 1 ; "0" no, "1" yes
- pm_lockbytes: .space 1 ; # of lock bytes
- pm_fusebytes: .space 1 ; # of fuse bytes
- pm_flpollval1: .space 1 ; Flash polling value
- pm_flpollval2: .space 1 ; Flash polling value
- pm_eepollval1: .space 1 ; EEPROM polling value
- pm_eepollval2: .space 1 ; EEPROM polling value
- pm_pagesizeh: .space 1 ; Page size high byte
- pm_pagesizel: .space 1 ; Page size low byte
- pm_eesizeh: .space 1 ; EEPROM size high byte
- pm_eesizel: .space 1 ; EEPROM size low byte
- pm_flsize4: .space 1 ; Flash size MSB
- pm_flsize3: .space 1 ; Flash size
- pm_flsize2: .space 1 ; Flash size
- pm_flsize1: .space 1 ; Flash size LSB
- ; *********************************************************************
- ; Vector table
- .section .text
- .global sisp
- sisp:
- rjmp main
- ; *********************************************************************
- ; Constant data
- .type signon_msg, @object
- .global signon_msg
- signon_msg:
- .string "\x14\x41VR STK\x10"
- .type version_msg, @object
- .global version_msg
- version_msg:
- .string "SISP 1.1.1 Copyright 2002-2003 by egnite Software GmbH\r\n"
- ; *********************************************************************
- ; Main program entry
- .global main
- main:
- ;
- ; Set stack pointer
- ldi r_temp, lo8(RAMEND)
- out _SFR_IO_ADDR(SPL), r_temp
- ;
- ; Initialize Port B
- ; PB2: ISP-LED z-state
- ; PB3: LED output low
- ; PB4: ISP-RESET z-state
- ; PB5: ISP-MOSI z-state
- ; PB6: ISP-MISO input
- ; PB7: ISP-SCK z-state
- clr r_temp
- out _SFR_IO_ADDR(PORTB), r_temp
- out _SFR_IO_ADDR(DDRB), r_temp
- sbi _SFR_IO_ADDR(DDRB), LEDIND
- ldi r_retry, 3
- blink:
- rcall xdelay
- rcall xdelay
- cbi _SFR_IO_ADDR(PORTB), LEDIND ; LED on
- ldi r_delay, 64
- rcall xdelay
- sbi _SFR_IO_ADDR(PORTB), LEDIND ; LED off
- dec r_retry
- brne blink
- ;
- ; Init UART
- ldi r_temp, BRFACTOR
- out _SFR_IO_ADDR(UBRR), r_temp
- ldi r_temp, (1<<RXEN) | (1<<TXEN)
- out _SFR_IO_ADDR(UCR), r_temp
- ;
- ; Set handshake line
- sbi _SFR_IO_ADDR(PORTD), HSOUT
- sbi _SFR_IO_ADDR(DDRD), HSOUT
- ; *********************************************************************
- ; Command handler
- cmdnxt:
- sbi _SFR_IO_ADDR(PORTB), LEDIND ; LED off
- rcall getc
- cbi _SFR_IO_ADDR(PORTB), LEDIND ; LED on
- ; *********************************************************************
- ; Version output
- cpi r_data, 0x18 ; Ctrl-X
- brne c30
- ldi r30, lo8(version_msg)
- ldi r31, hi8(version_msg)
- rjmp c31a
- ; *********************************************************************
- ; PC command: Get synchronization.
- ;
- ; The PC uses this command to regain synchronization with the
- ; programmer. The command may be send several times until the
- ; programmer responds with STK_INSYNC.
- c30:
- cpi r_data, 0x30 ; '0'
- brne c31
- ; Receive last character of a command. If it's an EOP, then
- ; respond with INSYNC. Otherwise send back NOSYNC.
- cmdend:
- rcall getc
- cpi r_data, CRC_EOP
- breq cmdok
- ldi r_data, STK_NOSYNC
- rcall putc
- rjmp cmdnxt ; Wait for next command
- ; Send back positive response.
- cmdok:
- ldi r_data, STK_INSYNC
- rcall putc
- cmdfirm:
- ldi r_data, STK_OK
- rcall putc
- rjmp cmdnxt ; Wait for next command
- ; *********************************************************************
- ; PC command: Check if starterkit present.
- ;
- ; The programmer responds with a sign-on message.
- ;
- c31:
- cpi r_data, 0x31 ; '1'
- brne c41
- rcall getc ; Ignore CRC_EOP
- ldi r30, lo8(signon_msg)
- ldi r31, hi8(signon_msg)
- c31a:
- lpm
- tst r0
- breq cmdnxt ; Done, wait for next command
- mov r_data, r0
- rcall putc
- adiw r30, 1
- rjmp c31a
- ; *********************************************************************
- ; PC command: Get parameter value
- c41:
- cpi r_data, 0x41 ; 'A'
- brne c42
- rcall getc ; Receive parameter id
- mov r_parm, r_data
- rcall getc ; Ignore CRC_EOP
- ldi r_data, STK_INSYNC
- rcall putc
- rcall getparm
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Set device programming parameters
- ;
- ; We ignore these parameters.
- c42:
- cpi r_data, 0x42 ; 'B'
- brne c45
- ldi r_size, 20
- _c42nxt:
- rcall getc
- dec r_size
- brne _c42nxt
- rjmp cmdend
- ; *********************************************************************
- ; PC command: Set extended device programming parameters
- ;
- ; We ignore these parameters.
- c45:
- cpi r_data, 0x45 ; 'E'
- brne c50
- ldi r_size, 5
- _c45nxt:
- rcall getc
- dec r_size
- brne _c45nxt
- rjmp cmdend
- ; *********************************************************************
- ; PC command: Enter Program Mode
- c50:
- cpi r_data, 0x50 ; 'P'
- brne c51
- rcall getc ; Ignore CRC_EOP
- ;
- ; Enable ISP interface.
- ; PB2: ISP-LED output low
- ; PB3: LED output low
- ; PB4: ISP-RESET output low
- ; PB5: ISP-MOSI output high
- ; PB6: ISP-MISO input
- ; PB7: ISP-SCK output low
- ldi r_temp, (1<<ISPMISO)
- out _SFR_IO_ADDR(PORTB), r_temp
- ldi r_temp, (1<<ISPLED)|(1<<LEDIND)|(1<<ISPRST)|(1<<ISPMOSI)|(1<<ISPSCK)
- out _SFR_IO_ADDR(DDRB), r_temp
- rcall xdelay
- ldi r_retry, 32
- ;
- ; Send programming enable
- c50a:
- ldi r_isp, 0xAC
- rcall ispxcg
- ldi r_isp, 0x53
- rcall ispxcg
- rcall ispget
- cpi r_isp, 0x53 ; Are we in sync
- breq c50z ; Yes, jump
- ;
- ; Handle sync failure
- rcall ispget ; Read last SPI byte
- sbi _SFR_IO_ADDR(PORTB), ISPRST ; Toggle target's reset line
- rcall xdelay
- cbi _SFR_IO_ADDR(PORTB), ISPRST
- rcall xdelay
- dec r_retry ; Loop for retries
- brne c50a
- rjmp cmdok ; Send positive resopnse
- c50z:
- rcall ispget
- rjmp cmdok ; Send positive resopnse
- ; *********************************************************************
- ; PC command: Leave program mode
- c51:
- cpi r_data, 0x51 ; 'Q'
- brne c52
- rcall getc ; Ignore CRC_EOP
- ;
- ; Disable ISP interface.
- ; PB2: ISP-LED z-state
- ; PB3: LED output low
- ; PB4: ISP-RESET z-state
- ; PB5: ISP-MOSI z-state
- ; PB6: ISP-MISO input
- ; PB7: ISP-SCK z-state
- clr r_temp
- out _SFR_IO_ADDR(PORTB), r_temp
- out _SFR_IO_ADDR(DDRB), r_temp
- sbi _SFR_IO_ADDR(DDRB), LEDIND
- rjmp cmdok ; Send positive resopnse
- ; *********************************************************************
- ; PC command: Chip erase
- c52:
- cpi r_data, 0x52 ; 'R'
- brne c55
- rcall getc
- ldi r_isp, 0xAC
- rcall ispxcg
- ldi r_isp, 0x80
- rcall ispxcg
- ldi r_isp, 0x04
- rcall ispxcg
- rcall ispget
- rcall xdelay ; Very long delay. May be reduced
- rcall xdelay ; but who really cares?
- rjmp cmdok ; Send positive resopnse
- ; *********************************************************************
- ; PC command: Load address
- c55:
- cpi r_data, 0x55 ; 'U'
- brne c56
- rcall getc
- sts paddrl, r_data
- rcall getc
- sts paddrh, r_data
- rjmp cmdend
- ; *********************************************************************
- ; PC command: Universal
- c56:
- cpi r_data, 0x56 ; 'V'
- brne c64
- rcall getc
- sts unicmd1, r_data
- rcall getc
- sts unicmd2, r_data
- rcall getc
- sts unicmd3, r_data
- rcall getc
- sts unicmd4, r_data
- rcall getc ; EOP
- ldi r_data, STK_INSYNC
- rcall putc
- lds r_isp, unicmd1
- rcall ispxcg
- lds r_isp, unicmd2
- rcall ispxcg
- lds r_isp, unicmd3
- rcall ispxcg
- lds r_isp, unicmd4
- rcall ispxcg
- ldi r_delay, 64
- rcall delay
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Program page
- ; This is a very tricky routine. The STK500 insists on sending
- ; data with 115,200 Baud. We hope, that the target MCU will be
- ; fast enough.
- c64:
- cpi r_data, 0x64 ; 'd'
- brne c72
- rcall getc ; Size of this block to Y-register
- mov r29, r_data
- rcall getc
- mov r28, r_data
- rcall getc ; Memory type (F)lash or (E)eprom
- cpi r_data, 'F'
- brne c64ee
- clr r30
- c64a:
- ldi r_isp, 0x40 ; Send low byte
- rcall ispput
- clr r_isp
- rcall ispput
- mov r_isp, r30
- rcall ispput
- c64b:
- sbis _SFR_IO_ADDR(USR), RXC
- rjmp c64b
- in r_isp, _SFR_IO_ADDR(UDR)
- rcall ispput
- ldi r_isp, 0x48 ; Send high byte
- rcall ispput
- clr r_isp
- rcall ispput
- mov r_isp, r30
- rcall ispput
- c64c:
- sbis _SFR_IO_ADDR(USR), RXC
- rjmp c64c
- in r_isp, _SFR_IO_ADDR(UDR)
- rcall ispput
- inc r30 ; Increment address
- sbiw r28, 2 ; Decrement length
- brne c64a
- rcall getc
- ldi r_isp, 0x4C ; Write memory page
- rcall ispxcg
- lds r_isp, paddrh
- rcall ispxcg
- lds r_isp, paddrl
- rcall ispxcg
- rcall ispget
- ldi r_delay, 168 ; Target requires delay after each write
- rcall delay ; We use 35 milliseconds, OK for most targets
- rjmp cmdok ; Send positive resopnse
- c64ee:
- c64ea:
- sbis _SFR_IO_ADDR(USR), RXC
- rjmp c64ea
- in r_isp, _SFR_IO_ADDR(UDR)
- c64ec:
- sbis _SFR_IO_ADDR(USR), RXC
- rjmp c64ec
- in r_isp, _SFR_IO_ADDR(UDR)
- sbiw r28, 2
- brne c64a
- rjmp cmdend
- ; *********************************************************************
- ; PC command: Read Fuse Bits
- c72:
- cpi r_data, 0x72 ; 'r'
- brne c73
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- ldi r_isp, 0x50 ; Read fuse bits command
- rcall ispxcg
- ldi r_isp, 0x00 ; Must be zero, don't care on mega103
- rcall ispxcg
- rcall ispget ; Don't care
- rcall ispget ; These are the bits
- mov r_data, r_isp
- rcall putc
- ; ATmega128 only
- ldi r_isp, 0x58 ; Read high fuses bits command
- rcall ispxcg
- ldi r_isp, 0x08 ; Must be 8
- rcall ispxcg
- rcall ispget ; Don't care
- rcall ispget ; Here we get them
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Lock Bits
- c73:
- cpi r_data, 0x73 ; 's'
- brne c74
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- ldi r_isp, 0x58
- rcall ispxcg
- ldi r_isp, 0x00
- rcall ispxcg
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Page
- c74:
- cpi r_data, 0x74 ; 't'
- brne c75
- rcall getc
- mov r29, r_data
- rcall getc
- mov r28, r_data
- rcall getc ; 'F' or 'E'
- cpi r_data, 'F'
- brne c74ee
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- lds r30, paddrl
- lds r31, paddrh
- c74a:
- ldi r_isp, 0x20
- rcall ispxcg
- mov r_isp, r31
- rcall ispxcg
- mov r_isp, r30
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- ldi r_isp, 0x28
- rcall ispxcg
- mov r_isp, r31
- rcall ispxcg
- mov r_isp, r30
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- adiw r30, 1
- sbiw r28, 2
- brne c74a
- rjmp cmdfirm
- c74ee:
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- lds r30, paddrl
- lds r31, paddrh
- c74ea:
- ldi r_isp, 0xA0
- rcall ispxcg
- mov r_isp, r31
- rcall ispxcg
- mov r_isp, r30
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- adiw r30, 1
- sbiw r28, 1
- brne c74ea
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Signature
- c75:
- cpi r_data, 0x75 ; 'u'
- brne c76
- rcall getc
- ldi r_data, STK_INSYNC
- rcall putc
- ldi r_isp, 0x30
- rcall ispxcg
- rcall ispget
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- ldi r_isp, 0x30
- rcall ispxcg
- rcall ispget
- ldi r_isp, 0x01
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- ldi r_isp, 0x30
- rcall ispxcg
- rcall ispget
- ldi r_isp, 0x02
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Oscillator Calibration Byte
- c76:
- cpi r_data, 0x76 ; 'v'
- brne c77
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- ldi r_isp, 0x38
- rcall ispxcg
- rcall ispget
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Fuse Bits Extended
- c77:
- cpi r_data, 0x77 ; 'w'
- brne c78
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- ldi r_isp, 0x50
- rcall ispxcg
- ldi r_isp, 0x00
- rcall ispxcg
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- ldi r_isp, 0x58
- rcall ispxcg
- ldi r_isp, 0x08
- rcall ispxcg
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- ldi r_isp, 0x50
- rcall ispxcg
- ldi r_isp, 0x08
- rcall ispxcg
- rcall ispget
- rcall ispget
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Read Oscillator Calibration Byte Extended
- c78:
- cpi r_data, 0x78 ; 'x'
- brne cbad
- rcall getc
- mov r30, r_data
- rcall getc ; EOP
- ldi r_data, STK_INSYNC ; INSYNC
- rcall putc
- ldi r_isp, 0x38
- rcall ispxcg
- rcall ispget
- mov r_isp, r30
- rcall ispxcg
- rcall ispget
- mov r_data, r_isp
- rcall putc
- rjmp cmdfirm
- ; *********************************************************************
- ; PC command: Unknown
- cbad:
- rjmp cmdend
- ; *********************************************************************
- ; *** GetParm
- getparm:
- ;
- ; Hardware version
- cpi r_parm, 0x80
- brne _gp81
- ldi r_data, 2
- ret
- ;
- ; Software version major
- _gp81:
- cpi r_parm, 0x81
- brne _gp82
- ldi r_data, 1
- ret
- ;
- ; Software version minor
- _gp82:
- cpi r_parm, 0x82
- brne _gp83
- ldi r_data, 14
- ret
- ;
- ; LEDs
- _gp83:
- cpi r_parm, 0x83
- brne _gp84
- ldi r_data, 1
- ret
- ;
- ; Target voltage
- _gp84:
- cpi r_parm, 0x84
- brne _gp85
- ldi r_data, 50
- ret
- ;
- ; Adjustable Voltage
- _gp85:
- cpi r_parm, 0x85
- brne _gp86
- ldi r_data, 50
- ret
- ;
- ; Oscillator timer prescaler value
- _gp86:
- cpi r_parm, 0x86
- brne _gp87
- ldi r_data, 0
- ret
- ;
- ; Oscillator timer compare match value
- _gp87:
- cpi r_parm, 0x87
- brne _gp88
- ldi r_data, 0
- ret
- ;
- ; Reset duration
- _gp88:
- cpi r_parm, 0x88
- brne _gp89
- ldi r_data, 0x30
- ret
- ;
- ; SCK duration
- _gp89:
- cpi r_parm, 0x89
- brne _gp90
- ldi r_data, 0x30
- ret
- ;
- ; Bufsiz low
- _gp90:
- cpi r_parm, 0x90
- brne _gp91
- ldi r_data, 64
- ret
- ;
- ; Bufsiz high
- _gp91:
- cpi r_parm, 0x91
- brne _gp92
- ldi r_data, 0
- ret
- ;
- ; Device
- _gp92:
- cpi r_parm, 0x92
- brne _gp93
- lds r_data, pm_devicecode
- ret
- ;
- ; Progmode
- _gp93:
- cpi r_parm, 0x93
- brne _gp94
- lds r_data, pm_progtype
- ret
- ;
- ; Para mode
- _gp94:
- cpi r_parm, 0x94
- brne _gp95
- lds r_data, pm_parmode
- ret
- ;
- ; Polling
- _gp95:
- cpi r_parm, 0x95
- brne _gp96
- lds r_data, pm_polling
- ret
- ;
- ; Self timed
- _gp96:
- cpi r_parm, 0x96
- brne _gpuk
- lds r_data, pm_selftimed
- ret
- ;
- ; Unknown
- _gpuk:
- clr r_data
- ret
- ;
- ; *********************************************************************
- ; UART routines
- ; The UART is used in polling mode.
- ; Receive a single byte into register r_data.
- ;
- ; This routine will not return until a byte is available.
- ;
- getc:
- sbis _SFR_IO_ADDR(USR), RXC
- rjmp getc
- in r_data, _SFR_IO_ADDR(UDR)
- ret
- ; Send a single byte passed in register r_data.
- ;
- putc:
- sbis _SFR_IO_ADDR(USR), UDRE
- rjmp putc
- out _SFR_IO_ADDR(UDR), r_data
- ret
- ; *********************************************************************
- ; Exchange ISP Byte
- ispget:
- clr r_isp
- ispxcg:
- ldi r_temp, 8
- clr r_shift
- ;
- ; Start of 8-bit loop
- _ispa:
- rol r_isp ; (1)
- brcc _ispb ; (2/1)
- sbi _SFR_IO_ADDR(PORTB), ISPMOSI ; (2)
- rjmp _ispc ; (2)
- _ispb:
- cbi _SFR_IO_ADDR(PORTB), ISPMOSI ; (2)
- _ispc:
- nop ; (1)
- sbi _SFR_IO_ADDR(PORTB), ISPSCK ; (2)
- lsl r_shift ; (1)
- sbic _SFR_IO_ADDR(PINB), ISPMISO ; (2/1)
- ori r_shift, 1 ; (1)
- cbi _SFR_IO_ADDR(PORTB), ISPSCK ; (2)
- ;
- ; End of 8-bit loop
- dec r_temp ; (1)
- brne _ispa ; (2/1)
- mov r_isp, r_shift ; (1)
- ret ; (4)
- ; *********************************************************************
- ; Send out a byte to ISP as fast as possible.
- ;
- ; Runtime calculation:
- ; + 7 cycles for rcall/return
- ; + 1 cycle to initially read the port status
- ; + 4 cycle to set the final port status
- ; + 48 cycles for output, 6 cycles per bit
- ; The total of 60 cycles takes 16.276 microseconds on a 3.6864 MHz MCU.
- ; At 115 kBaud a new character is received every 86.8 microsecond.
- ; The SCK low time is 814 nanoseconds and the high time is 543 nanoseconds.
- ; Following the datasheet, the target requires a minimum SCK low and
- ; high time of 2 clock cycles. So we may not be able to program targets
- ; running with same or higher crystals than our own.
- ; Tests with an ATmega128 showed, that it was possible to program the
- ; chip while running on its internal oscillator down to 2 MHz.
- ;
- ispput: ; (3) Costly call
- in r_temp, _SFR_IO_ADDR(PORTB) ; (1) Load current port status
- bst r_isp, 7 ; (1) Bit7 -> T
- bld r_temp, ISPMOSI ; (1) T -> MOSI
- out _SFR_IO_ADDR(PORTB), r_temp ; (1) Output, SCK still low
- sbi _SFR_IO_ADDR(PORTB), ISPSCK ; (2) SCK high
- bst r_isp, 6 ; (1)
- bld r_temp, ISPMOSI ; (1)
- out _SFR_IO_ADDR(PORTB), r_temp ; SCK back to low after about 3 cycles
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK ; SCK high again after about 2 cycles
- bst r_isp, 5
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- bst r_isp, 4
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- bst r_isp, 3
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- bst r_isp, 2
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- bst r_isp, 1
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- bst r_isp, 0
- bld r_temp, ISPMOSI
- out _SFR_IO_ADDR(PORTB), r_temp
- nop
- sbi _SFR_IO_ADDR(PORTB), ISPSCK
- nop
- nop
- nop
- out _SFR_IO_ADDR(PORTB), r_temp ; (1) SCK low
- ret ; (4) Costly return
- ; *********************************************************************
- ; Delay
- ;
- ; xdelay takes about 53.6 ms
- xdelay: ; (3)
- clr r_delay ; (1)
- delay:
- clr r_temp ; (1) Outer loop with r_delay * 772 cycles
- dl:
- dec r_temp ; (1) Inner loop with 3 cycles
- brne dl ; (2/1)
- dec r_delay ; (1)
- brne delay ; (2/1)
- ret ; (4)
- #ifdef SISPDEBUG
- ; *********************************************************************
- ; Debug
- ;
- puthexb:
- push r_data
- swap r_data
- rcall puthexc
- pop r_data
- puthexc:
- push r_temp
- mov r_temp, r_data
- andi r_temp, 0x0f
- subi r_temp, -'0'
- cpi r_temp, 0x3a
- brlo _putx1
- subi r_temp, -7
- _putx1:
- push r_data
- mov r_data, r_temp
- rcall putc
- pop r_data
- pop r_temp
- ret
- #endif
|