; This program is meant to run on an ATmega328P that is running at 16MHz ;in the flash programming circuit. So far, the only device that is supported ;is the Winbond W29EE011 128KB flash memory. Future memories may include ;SST 39SF020a 256KB, Winbond W29C020 256KB, and Winbond W49F002U 256KB. ; Flash data is at the bottom of the program and page address is in the ;equates. .nolist .include "m328Pdef.inc" .list .def id0 = r14 .def id1 = r15 .def shftl = r16 .def shftm = r17 .def shfth = r18 .def reg = r19 .def reg2 = r20 .def count = r21 ;Port C .equ led = 0 .equ clear = 1 .equ clk = 2 .equ data = 3 .equ re = 4 .equ we = 5 ;Port B .equ buzzer = 1 ;ID # .equ W29EE011 = 0xC1 .equ Winbond = 0xDA ;START ADDRESS GOES HERE: .equ addrh = 0x00 ;High byte of address. .equ addrm = 0x00 ;Middle byte of address. .equ addrl = 0x00 ;Low byte of address. .cseg .org 0x0000 ;remove alot of reti commands. has not been tested since. start: ldi reg,0b00111100 ;Clear shift registers and set port C data direction. out PORTC,reg ldi reg,0b00111111 out DDRC,reg ldi reg,0b00111110 out PORTC,reg rcall tone ;Start up tone. rcall flashID ;Find the part number of the chip. ldi reg,Winbond cp id0,reg breq progWinbond set ;Set error bit if the device is not supported. rjmp error verify: ;Check flash to make sure that it is correct. ldi reg,Winbond cp id0,reg breq verWinbond set error: in reg,SREG sbrc reg,SREG_T ;Turn on LED if there was a programming error. sbi PORTC,led rcall tone ;Announce that the program has ended. end: ;End nop rjmp end ;Determine which type of Winbond flash to verify. verWinbond: ldi reg,W29EE011 cp id1,reg breq verW29EE011 set rjmp error ;Check that the programmed data is correct. verW29EE011: ldi shfth,addrh ldi shftm,addrm ldi shftl,addrl ldi ZH,HIGH(bytes*2) ldi ZL,LOW(bytes*2) ldi reg,0x00 ;Disable outputs out DDRD,reg out PORTD,reg cbi PORTC,re ;Enable flash outputs ldi count,128 verW29EE011Loop: rcall shiftPort lpm reg,Z+ in reg2,PIND cp reg,reg2 ;Compare written data with intended data. in reg,SREG sbrs reg,SREG_Z ;Set T if data doesn't equal the intended data. set nop ldi reg,0x01 add shftl,reg ldi reg,0x00 adc shftm,reg adc shfth,reg dec count brne verW29EE011Loop sbi PORTC,re rjmp error ;Determine which type of Winbond flash to program. progWinbond: ldi reg,W29EE011 cp id1,reg breq progW29EE011 set ;Set error bit if the device is not supported. rjmp error progW29EE011: sbi PORTC,re ;Software data protection temporary disable. ldi reg,0xFF out DDRD,reg ldi shfth,0x00 ;Write AA to 5555 ldi shftm,0x55 ldi shftl,0x55 rcall shiftPort ldi reg,0xAA out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x2A ;Write 55 to 2AAA ldi shftl,0xAA rcall shiftPort ldi reg,0x55 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x55 ;Write A0 to 5555 ldi shftl,0x55 rcall shiftPort ldi reg,0xA0 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shfth,addrh ;Load shft with flash page address. ldi shftm,addrm ldi shftl,addrl ldi ZH,HIGH(bytes*2) ;Load Z with the address of the data to be ldi ZL,LOW(bytes*2) ;programmed. ldi count,128 ;Repeat 128 times progW29EE011Loop: rcall shiftPort ;Shift out address. lpm reg,Z+ ;Move byte to be programmed to port D. out PORTD,reg cbi PORTC,we ;Pulse !WE. nop sbi PORTC,we ldi reg,0x01 ;Increment shft. add shftl,reg ldi reg,0x00 adc shftm,reg adc shfth,reg dec count ;Decrement count. brne progW29EE011Loop ;If count = 0x00 then wait 15ms. ldi XH,0x3A ldi XL,0x98 progW29EE011delay: sbiw X,0x0001 nop ;Never do this unless you have a lot of room. nop nop nop nop nop nop nop nop nop nop nop brne progW29EE011delay rjmp verify ;flashID subroutine flashID: ;Product identification entry: sbi PORTC,re ;Disable flash outputs. ldi reg,0xFF ;Set port D to output. out DDRD,reg ldi shfth,0x00 ;write AA to 5555 ldi shftm,0x55 ldi shftl,0x55 rcall shiftPort ;Set address. ldi reg,0xAA ;Set data. out PORTD,reg cbi PORTC,we ;Pulse !WE. nop sbi PORTC,we ldi shftm,0x2A ;Write 55 to 2AAA. ldi shftl,0xAA rcall shiftPort ldi reg,0x55 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x55 ;Write 80 to 5555. ldi shftl,0x55 rcall shiftPort ldi reg,0x80 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x55 ;Write AA to 5555. ldi shftl,0x55 rcall shiftPort ldi reg,0xAA out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x2A ;Write 55 to 2AAA. ldi shftl,0xAA rcall shiftPort ldi reg,0x55 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x55 ;Write 60 to 5555. ldi shftl,0x55 rcall shiftPort ldi reg,0x60 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi reg,60 ;pause 10 us PIEnWait: dec reg brne PIEnWait ;Product identification mode: ldi reg,0x00 ;Set port D to input out DDRD,reg out PORTD,reg ;Read manufacture's ID. ldi shftm,0 ;load address 0 ldi shftl,0 cbi PORTC,re ;read byte from address 0 rcall shiftPort in reg,PIND mov id0,reg ;Read device ID. ldi shftl,0x01 ;Load address 1 rcall shiftPort in reg,PIND ;Read byte from address 1 mov id1,reg sbi PORTC,re ;disable flash outputs ;Product identification Exit: ldi reg,0xFF ;Set port D to output out DDRD,reg ldi shftm,0x55 ;Write AA to 5555 ldi shftl,0x55 rcall shiftPort ldi reg,0xAA out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x2A ;Write 55 to 2AAA ldi shftl,0xAA rcall shiftPort ldi reg,0x55 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi shftm,0x55 ;Write F0 to 5555 ldi shftl,0x55 rcall shiftPort ldi reg,0xF0 out PORTD,reg cbi PORTC,we nop sbi PORTC,we ldi reg,60 ;pause 10 us PIExWait: dec reg brne PIExWait ret ;shiftPort subroutine shiftPort: cbi PORTC,clk sbrc shfth,7 sbi PORTC,data sbrs shfth,7 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,6 sbi PORTC,data sbrs shfth,6 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,5 sbi PORTC,data sbrs shfth,5 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,4 sbi PORTC,data sbrs shfth,4 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,3 sbi PORTC,data sbrs shfth,3 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,2 sbi PORTC,data sbrs shfth,2 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,1 sbi PORTC,data sbrs shfth,1 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shfth,0 sbi PORTC,data sbrs shfth,0 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,7 sbi PORTC,data sbrs shftm,7 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,6 sbi PORTC,data sbrs shftm,6 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,5 sbi PORTC,data sbrs shftm,5 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,4 sbi PORTC,data sbrs shftm,4 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,3 sbi PORTC,data sbrs shftm,3 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,2 sbi PORTC,data sbrs shftm,2 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,1 sbi PORTC,data sbrs shftm,1 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftm,0 sbi PORTC,data sbrs shftm,0 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,7 sbi PORTC,data sbrs shftl,7 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,6 sbi PORTC,data sbrs shftl,6 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,5 sbi PORTC,data sbrs shftl,5 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,4 sbi PORTC,data sbrs shftl,4 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,3 sbi PORTC,data sbrs shftl,3 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,2 sbi PORTC,data sbrs shftl,2 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,1 sbi PORTC,data sbrs shftl,1 cbi PORTC,data sbi PORTC,clk cbi PORTC,clk sbrc shftl,0 sbi PORTC,data sbrs shftl,0 cbi PORTC,data sbi PORTC,clk ret ;Tone subroutine tone: push XL ;Save X and Y push XH push YL push YH sbi DDRD,buzzer ;Set pin PD4 to output ldi YL,0x93 ;play tone for one second ldi YH,0x11 toneMain: sbi DDRB,buzzer ;Buzzer pin is an output. sbi PORTB, buzzer ;buzzer is high ldi XL,0xBB ;Set tone frequency to 4.5kHz ldi XH,0x01 ;Do not set X to less than one. toneDelay1: sbiw X,0x0001 brne toneDelay1 cbi PORTB, buzzer ;buzzer is low ldi XL, 0xBB ;Set X again ldi XH,0x01 toneDelay2: sbiw X,0x0001 brne toneDelay2 sbiw Y,0x0001 ;decrement Y brne toneMain ;resart cycle if Y is not zero cbi DDRB,buzzer ;Three state PD4 pop YH ;restore X and Y to their former values pop YL pop XH pop XL ret ;The 128 bytes to be programmed: bytes: ; 0 1 2 3 4 5 6 7 .db 0xDB,0x00,0xD3,0x00,0xC3,0x00,0x00,0xFF ;0 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;1 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;2 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;3 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;4 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;5 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;6 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;7 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;10 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;11 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;12 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;13 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;14 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;15 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;16 .db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF ;17