self-program.elf: file format elf32-avr Disassembly of section .bootloader: 00000d00 : //115,200 is the only supported mode. GENFNHDR __attribute__ ((noreturn, naked)) void Bootloader() { //Program preamble, i.e. bss set, clear stuff. asm volatile( "\n\t\ d00: 11 24 eor r1, r1 d02: 1f be out 0x3f, r1 ; 63 d04: cf ef ldi r28, 0xFF ; 255 d06: d1 e0 ldi r29, 0x01 ; 1 d08: de bf out 0x3e, r29 ; 62 d0a: cd bf out 0x3d, r28 ; 61 d0c: 21 e0 ldi r18, 0x01 ; 1 d0e: a0 e0 ldi r26, 0x00 ; 0 d10: b1 e0 ldi r27, 0x01 ; 1 d12: 01 c0 rjmp .+2 ; 0xd16 d14: 1d 92 st X+, r1 d16: a0 31 cpi r26, 0x10 ; 16 d18: b2 07 cpc r27, r18 d1a: e1 f7 brne .-8 ; 0xd14 cpi r26, 0x10 ; 16\n\t\ cpc r27, r18\n\t\ brne .-8 ; 0x50 <.do_clear_bss_loop>\n\t\ " ); cli(); //Yes, I know this is redundant... kept as a placeholder. d1c: f8 94 cli WSDDR |= WSPIN; d1e: ba 9a sbi 0x17, 2 ; 23 CCP = 0xD8; d20: 88 ed ldi r24, 0xD8 ; 216 d22: 80 93 71 00 sts 0x0071, r24 CLKPR = 1; //Divide-by-two clock. d26: 81 e0 ldi r24, 0x01 ; 1 d28: 80 93 73 00 sts 0x0073, r24 //Read the 14.7 MHz line out from flash then set OSCCAL0 based on that. asm volatile( "\n\t\ d2c: e7 ee ldi r30, 0xE7 ; 231 d2e: ff e0 ldi r31, 0x0F ; 15 d30: 94 90 lpm r9, Z d32: 90 92 74 00 sts 0x0074, r9 ldi r31, hi8(caldata+23)\n\t\ lpm r9, Z\n\t\ sts 0x0074, r9; OSCCAL0\n\t" ); volatile uint8_t vc = UDR0; d36: 80 91 80 00 lds r24, 0x0080 vc = vc; //Flush out any pending UDRs UCSR0A = 0; d3a: 10 92 86 00 sts 0x0086, r1 UCSR0B = 0; d3e: 10 92 85 00 sts 0x0085, r1 UCSR0C = 0; d42: 10 92 84 00 sts 0x0084, r1 UCSR0D = 0; d46: 10 92 83 00 sts 0x0083, r1 //RXD0 is our RX; on PA2 DDRA &= ~_BV(2); d4a: d2 98 cbi 0x1a, 2 ; 26 UBRR0H = 0; d4c: 10 92 82 00 sts 0x0082, r1 UBRR0L = 0x03; d50: 23 e0 ldi r18, 0x03 ; 3 d52: 20 93 81 00 sts 0x0081, r18 UCSR0A = 0; d56: 10 92 86 00 sts 0x0086, r1 UCSR0B = _BV(RXEN0); //Enable RX + No interrupt. d5a: 80 e1 ldi r24, 0x10 ; 16 d5c: 80 93 85 00 sts 0x0085, r24 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); d60: 96 e0 ldi r25, 0x06 ; 6 d62: 90 93 84 00 sts 0x0084, r25 UCSR0D = 0; d66: 10 92 83 00 sts 0x0083, r1 REMAP &= ~_BV(U0MAP); d6a: 80 91 65 00 lds r24, 0x0065 d6e: 8e 7f andi r24, 0xFE ; 254 d70: 80 93 65 00 sts 0x0065, r24 //TXD1 is our TX; on PA5 DDRA |= _BV(5); d74: d5 9a sbi 0x1a, 5 ; 26 UBRR1H = 0; d76: 10 92 92 00 sts 0x0092, r1 UBRR1L = 0x03; d7a: 20 93 91 00 sts 0x0091, r18 UCSR1A = 0; d7e: 10 92 96 00 sts 0x0096, r1 UCSR1B = _BV(TXEN1); d82: 88 e0 ldi r24, 0x08 ; 8 d84: 80 93 95 00 sts 0x0095, r24 UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); d88: 90 93 94 00 sts 0x0094, r25 UCSR1D = 0; d8c: 10 92 93 00 sts 0x0093, r1 SendWS2812Single( 0x20, 0x20, 0x00 ); d90: 40 e0 ldi r20, 0x00 ; 0 d92: 60 e2 ldi r22, 0x20 ; 32 d94: 80 e2 ldi r24, 0x20 ; 32 d96: e1 d0 rcall .+450 ; 0xf5a //All hardware is set up now. xfoffset = 0xff; d98: aa 24 eor r10, r10 d9a: aa 94 dec r10 if( b == 0 ) { uint16_t pos = msgbuffer[2] | (msgbuffer[1] << 8); while ( !( UCSR1A & (1< b = UDR0; da6: 80 91 80 00 lds r24, 0x0080 daa: 88 2e mov r8, r24 UDR1 = b; dac: 80 93 90 00 sts 0x0090, r24 len = b>>4; db0: 98 2f mov r25, r24 db2: 92 95 swap r25 db4: 9f 70 andi r25, 0x0F ; 15 db6: 69 2e mov r6, r25 cmd = b&15; db8: 8f 70 andi r24, 0x0F ; 15 dba: 78 2e mov r7, r24 for( i = 0; i < len; i++ ) dbc: 91 2c mov r9, r1 dbe: 10 c0 rjmp .+32 ; 0xde0 { while ( !(UCSR0A & _BV(RXC0)) ); dc0: 80 91 86 00 lds r24, 0x0086 dc4: 87 ff sbrs r24, 7 dc6: fc cf rjmp .-8 ; 0xdc0 vc = UDR0; dc8: 20 91 80 00 lds r18, 0x0080 UDR1 = vc; dcc: 20 93 90 00 sts 0x0090, r18 msgbuffer[i] = vc; dd0: 89 2d mov r24, r9 dd2: e9 2d mov r30, r9 dd4: f0 e0 ldi r31, 0x00 ; 0 dd6: e0 50 subi r30, 0x00 ; 0 dd8: ff 4f sbci r31, 0xFF ; 255 dda: 20 83 st Z, r18 UDR1 = b; len = b>>4; cmd = b&15; for( i = 0; i < len; i++ ) ddc: 8f 5f subi r24, 0xFF ; 255 dde: 98 2e mov r9, r24 de0: 99 16 cp r9, r25 de2: 70 f3 brcs .-36 ; 0xdc0 UDR1 = vc; msgbuffer[i] = vc; } //Process the command. switch( cmd ) de4: 87 2d mov r24, r7 de6: 8b 30 cpi r24, 0x0B ; 11 de8: 99 f0 breq .+38 ; 0xe10 dea: 18 f4 brcc .+6 ; 0xdf2 dec: 82 30 cpi r24, 0x02 ; 2 dee: 41 f0 breq .+16 ; 0xe00 df0: d6 cf rjmp .-84 ; 0xd9e df2: 8c 30 cpi r24, 0x0C ; 12 df4: 09 f4 brne .+2 ; 0xdf8 df6: 39 c0 rjmp .+114 ; 0xe6a df8: 8d 30 cpi r24, 0x0D ; 13 dfa: 09 f4 brne .+2 ; 0xdfe dfc: 66 c0 rjmp .+204 ; 0xeca dfe: cf cf rjmp .-98 ; 0xd9e { case 2: //A WS2812 Command. //ignores msgbuffer[0] SendWS2812Single( msgbuffer[1], msgbuffer[2], msgbuffer[3] ); e00: 40 91 03 01 lds r20, 0x0103 e04: 60 91 02 01 lds r22, 0x0102 e08: 80 91 01 01 lds r24, 0x0101 e0c: a6 d0 rcall .+332 ; 0xf5a break; e0e: c7 cf rjmp .-114 ; 0xd9e case 11: //Erase 4-page - address must be 4-page aligned. if( len != 5 ) break; e10: 95 30 cpi r25, 0x05 ; 5 e12: 29 f6 brne .-118 ; 0xd9e if( msgbuffer[0] >= 0xd ) break; //Can't write into bootloader e14: 30 91 00 01 lds r19, 0x0100 e18: 3d 30 cpi r19, 0x0D ; 13 e1a: 08 f6 brcc .-126 ; 0xd9e if( msgbuffer[1] & (SPM_PAGESIZE*4-1) ) break; //Must be byte-aligned. e1c: 20 91 01 01 lds r18, 0x0101 e20: 82 2f mov r24, r18 e22: 8f 73 andi r24, 0x3F ; 63 e24: 09 f0 breq .+2 ; 0xe28 e26: bb cf rjmp .-138 ; 0xd9e if( msgbuffer[4] != 'P' ) break; e28: 80 91 04 01 lds r24, 0x0104 e2c: 80 35 cpi r24, 0x50 ; 80 e2e: 09 f0 breq .+2 ; 0xe32 e30: b6 cf rjmp .-148 ; 0xd9e sadyMSB = msgbuffer[0]; sadyLSB = msgbuffer[1]; e32: 29 01 movw r4, r18 //Dunno why, nice bitwise logic makes the compiler puke. if( sadyMSB + msgbuffer[2] != 0xff ) break; e34: 80 91 02 01 lds r24, 0x0102 e38: 90 e0 ldi r25, 0x00 ; 0 e3a: 83 0f add r24, r19 e3c: 91 1d adc r25, r1 e3e: 8f 3f cpi r24, 0xFF ; 255 e40: 91 05 cpc r25, r1 e42: 09 f0 breq .+2 ; 0xe46 e44: ac cf rjmp .-168 ; 0xd9e if( sadyLSB + msgbuffer[3] != 0xff ) break; e46: 80 91 03 01 lds r24, 0x0103 e4a: 90 e0 ldi r25, 0x00 ; 0 e4c: 82 0f add r24, r18 e4e: 91 1d adc r25, r1 e50: 8f 3f cpi r24, 0xFF ; 255 e52: 91 05 cpc r25, r1 e54: 09 f0 breq .+2 ; 0xe58 e56: a3 cf rjmp .-186 ; 0xd9e //ZH = r31, ZL = r30. //XXX WARNING: The erase waiting doesn't seem to actually work. asm volatile ("\n\t\ e58: f2 01 movw r30, r4 e5a: 13 e0 ldi r17, 0x03 ; 3 e5c: 17 bf out 0x37, r17 ; 55 e5e: e8 95 spm 00000e60 : e60: 17 b7 in r17, 0x37 ; 55 e62: 10 fd sbrc r17, 0 e64: fd cf rjmp .-6 ; 0xe60 : [SPGREG] "I" (_SFR_IO_ADDR(SPMCSR) ) : "r17", "r30", "r31" ); //XXX TODO: WAIT FOR WRITE TO COMPLETE!!! xfoffset = 0; e66: a1 2c mov r10, r1 break; e68: 9a cf rjmp .-204 ; 0xd9e case 12: //Load 1/2 page (will write in the 4 pages that were erased) Call 8 times! { if( len != 8 ) break; e6a: 98 30 cpi r25, 0x08 ; 8 e6c: 09 f0 breq .+2 ; 0xe70 e6e: 97 cf rjmp .-210 ; 0xd9e if( xfoffset >= 2*4 ) break; //Can only write 4 pages at a time, and only if erased. If it's not, it's set to 0xff e70: 87 e0 ldi r24, 0x07 ; 7 e72: 8a 15 cp r24, r10 e74: 08 f4 brcc .+2 ; 0xe78 e76: 93 cf rjmp .-218 ; 0xd9e SendWS2812Single( 0x00, 0xff, 0x00 ); e78: 40 e0 ldi r20, 0x00 ; 0 e7a: 6f ef ldi r22, 0xFF ; 255 e7c: 80 e0 ldi r24, 0x00 ; 0 e7e: 6d d0 rcall .+218 ; 0xf5a //Do writes... asm volatile ("\n\t\ e80: 0f 92 push r0 e82: 1f 92 push r1 e84: 24 e0 ldi r18, 0x04 ; 4 e86: a0 e0 ldi r26, 0x00 ; 0 e88: b1 e0 ldi r27, 0x01 ; 1 e8a: 11 e0 ldi r17, 0x01 ; 1 e8c: f2 01 movw r30, r4 00000e8e : e8e: 0d 90 ld r0, X+ e90: 1d 90 ld r1, X+ e92: 17 bf out 0x37, r17 ; 55 e94: e8 95 spm e96: ee 5f subi r30, 0xFE ; 254 e98: 2a 95 dec r18 e9a: c9 f7 brne .-14 ; 0xe8e e9c: a3 94 inc r10 e9e: a0 fc sbrc r10, 0 ea0: 08 c0 rjmp .+16 ; 0xeb2 ea2: 15 e0 ldi r17, 0x05 ; 5 ea4: f2 01 movw r30, r4 ea6: e0 7f andi r30, 0xF0 ; 240 ea8: 17 bf out 0x37, r17 ; 55 eaa: e8 95 spm 00000eac : eac: 17 b7 in r17, 0x37 ; 55 eae: 10 fd sbrc r17, 0 eb0: fd cf rjmp .-6 ; 0xeac 00000eb2 : eb2: 1f 90 pop r1 eb4: 0f 90 pop r0 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); eb6: 9a e4 ldi r25, 0x4A ; 74 eb8: 9a 95 dec r25 eba: f1 f7 brne .-4 ; 0xeb8 " : [sadym] "=r"(sadyMSB), [sadyl] "=r"(sadyLSB) : [SPGREG] "I" (_SFR_IO_ADDR(SPMCSR) ), [tmpoff] "r" (xfoffset) : "r18", "r17", "r26", "r27", "r30", "r31" ); _delay_us(15); SendWS2812Single( xfoffset, 0, 0 ); ebc: 40 e0 ldi r20, 0x00 ; 0 ebe: 60 e0 ldi r22, 0x00 ; 0 ec0: 8a 2d mov r24, r10 ec2: 4b d0 rcall .+150 ; 0xf5a sadyLSB += 8; ec4: 88 e0 ldi r24, 0x08 ; 8 ec6: 48 0e add r4, r24 break; ec8: 6a cf rjmp .-300 ; 0xd9e case 13: { //You send this 0x3d 0xff addyH addyL // then, send: 0x1d [id] < Will resend unless ID = 0, with id--... Then, 0x80 [8 bytes of data ...] if( len != 3 ) break; eca: 93 30 cpi r25, 0x03 ; 3 ecc: 09 f0 breq .+2 ; 0xed0 ece: 67 cf rjmp .-306 ; 0xd9e if( msgbuffer[0] != 0xff ) break; ed0: 80 91 00 01 lds r24, 0x0100 ed4: 8f 3f cpi r24, 0xFF ; 255 ed6: 09 f0 breq .+2 ; 0xeda ed8: 62 cf rjmp .-316 ; 0xd9e while ( !(UCSR0A & _BV(RXC0)) ); eda: 80 91 86 00 lds r24, 0x0086 ede: 87 ff sbrs r24, 7 ee0: fc cf rjmp .-8 ; 0xeda b = UDR0; ee2: 80 91 80 00 lds r24, 0x0080 ee6: 88 2e mov r8, r24 while ( !( UCSR1A & (1< UDR1 = b; ef0: 80 93 90 00 sts 0x0090, r24 if( b != 0x1d ) break; ef4: 8d 31 cpi r24, 0x1D ; 29 ef6: 09 f0 breq .+2 ; 0xefa ef8: 52 cf rjmp .-348 ; 0xd9e while ( !(UCSR0A & _BV(RXC0)) ); efa: 80 91 86 00 lds r24, 0x0086 efe: 87 ff sbrs r24, 7 f00: fc cf rjmp .-8 ; 0xefa b = UDR0; f02: 80 91 80 00 lds r24, 0x0080 f06: 88 2e mov r8, r24 while ( !( UCSR1A & (1< UDR1 = b-1; f10: 9f ef ldi r25, 0xFF ; 255 f12: 98 0f add r25, r24 f14: 90 93 90 00 sts 0x0090, r25 if( b == 0 ) f18: 81 11 cpse r24, r1 f1a: 41 cf rjmp .-382 ; 0xd9e { uint16_t pos = msgbuffer[2] | (msgbuffer[1] << 8); f1c: 80 91 01 01 lds r24, 0x0101 f20: 90 e0 ldi r25, 0x00 ; 0 f22: 98 2f mov r25, r24 f24: 88 27 eor r24, r24 f26: 20 91 02 01 lds r18, 0x0102 f2a: 82 2b or r24, r18 while ( !( UCSR1A & (1< UDR1 = 0x80; f34: c0 93 90 00 sts 0x0090, r28 for( i = 0; i < 8; i++ ) f38: 91 2c mov r9, r1 f3a: 0b c0 rjmp .+22 ; 0xf52 { while ( !( UCSR1A & (1< UDR1 = pgm_read_byte( pos + i ); f44: fc 01 movw r30, r24 f46: e2 0f add r30, r18 f48: f1 1d adc r31, r1 f4a: e4 91 lpm r30, Z f4c: e0 93 90 00 sts 0x0090, r30 if( b == 0 ) { uint16_t pos = msgbuffer[2] | (msgbuffer[1] << 8); while ( !( UCSR1A & (1< f58: 22 cf rjmp .-444 ; 0xd9e 00000f5a : #ifdef ASM_WS void WSSECTION SendWS2812Single( uint8_t r, uint8_t g, uint8_t b ) { asm volatile ("\n\t\ f5a: ba 9a sbi 0x17, 2 ; 23 f5c: 4f 93 push r20 f5e: 6f 93 push r22 f60: 8f 93 push r24 f62: 43 e0 ldi r20, 0x03 ; 3 00000f64 : f64: 5f 91 pop r21 f66: 68 e0 ldi r22, 0x08 ; 8 00000f68 : f68: 57 ff sbrs r21, 7 f6a: 06 c0 rjmp .+12 ; 0xf78 f6c: 32 e0 ldi r19, 0x02 ; 2 f6e: c2 9a sbi 0x18, 2 ; 24 f70: 3a 95 dec r19 f72: f1 f7 brne .-4 ; 0xf70 f74: c2 98 cbi 0x18, 2 ; 24 f76: 05 c0 rjmp .+10 ; 0xf82 00000f78 : f78: c2 9a sbi 0x18, 2 ; 24 f7a: c2 98 cbi 0x18, 2 ; 24 f7c: 32 e0 ldi r19, 0x02 ; 2 f7e: 3a 95 dec r19 f80: f1 f7 brne .-4 ; 0xf7e 00000f82 : f82: 55 0f add r21, r21 f84: 6a 95 dec r22 f86: 81 f7 brne .-32 ; 0xf68 f88: 4a 95 dec r20 f8a: 61 f7 brne .-40 ; 0xf64 f8c: 08 95 ret Disassembly of section .caldata: 00000fd0 : fd0: 5b ba out 0x1b, r5 ; 27 fd2: 92 09 sbc r25, r2 fd4: 59 e0 ldi r21, 0x09 ; 9 fd6: 43 6e ori r20, 0xE3 ; 227 fd8: f3 f4 brvc .+60 ; 0x1016 fda: c8 16 cp r12, r24 fdc: b6 93 lac Z, r27 fde: 8d 21 and r24, r13 fe0: 80 05 cpc r24, r0 fe2: 63 75 andi r22, 0x53 ; 83 fe4: 95 b5 in r25, 0x25 ; 37 fe6: bf 9d mul r27, r15 Disassembly of section .text: 00000000 <__vectors>: 0: 1d c0 rjmp .+58 ; 0x3c <__ctors_end> 2: 2c c0 rjmp .+88 ; 0x5c <__bad_interrupt> 4: 2b c0 rjmp .+86 ; 0x5c <__bad_interrupt> 6: 2a c0 rjmp .+84 ; 0x5c <__bad_interrupt> 8: 29 c0 rjmp .+82 ; 0x5c <__bad_interrupt> a: 28 c0 rjmp .+80 ; 0x5c <__bad_interrupt> c: 27 c0 rjmp .+78 ; 0x5c <__bad_interrupt> e: 26 c0 rjmp .+76 ; 0x5c <__bad_interrupt> 10: 25 c0 rjmp .+74 ; 0x5c <__bad_interrupt> 12: 24 c0 rjmp .+72 ; 0x5c <__bad_interrupt> 14: 23 c0 rjmp .+70 ; 0x5c <__bad_interrupt> 16: 22 c0 rjmp .+68 ; 0x5c <__bad_interrupt> 18: 21 c0 rjmp .+66 ; 0x5c <__bad_interrupt> 1a: 20 c0 rjmp .+64 ; 0x5c <__bad_interrupt> 1c: 1f c0 rjmp .+62 ; 0x5c <__bad_interrupt> 1e: 1e c0 rjmp .+60 ; 0x5c <__bad_interrupt> 20: 1d c0 rjmp .+58 ; 0x5c <__bad_interrupt> 22: 1c c0 rjmp .+56 ; 0x5c <__bad_interrupt> 24: 1b c0 rjmp .+54 ; 0x5c <__bad_interrupt> 26: 1a c0 rjmp .+52 ; 0x5c <__bad_interrupt> 28: 19 c0 rjmp .+50 ; 0x5c <__bad_interrupt> 2a: 18 c0 rjmp .+48 ; 0x5c <__bad_interrupt> 2c: 17 c0 rjmp .+46 ; 0x5c <__bad_interrupt> 2e: 16 c0 rjmp .+44 ; 0x5c <__bad_interrupt> 30: 15 c0 rjmp .+42 ; 0x5c <__bad_interrupt> 32: 14 c0 rjmp .+40 ; 0x5c <__bad_interrupt> 34: 13 c0 rjmp .+38 ; 0x5c <__bad_interrupt> 36: 12 c0 rjmp .+36 ; 0x5c <__bad_interrupt> 38: 11 c0 rjmp .+34 ; 0x5c <__bad_interrupt> 3a: 10 c0 rjmp .+32 ; 0x5c <__bad_interrupt> 0000003c <__ctors_end>: 3c: 11 24 eor r1, r1 3e: 1f be out 0x3f, r1 ; 63 40: cf ef ldi r28, 0xFF ; 255 42: d1 e0 ldi r29, 0x01 ; 1 44: de bf out 0x3e, r29 ; 62 46: cd bf out 0x3d, r28 ; 61 00000048 <__do_clear_bss>: 48: 21 e0 ldi r18, 0x01 ; 1 4a: a0 e0 ldi r26, 0x00 ; 0 4c: b1 e0 ldi r27, 0x01 ; 1 4e: 01 c0 rjmp .+2 ; 0x52 <.do_clear_bss_start> 00000050 <.do_clear_bss_loop>: 50: 1d 92 st X+, r1 00000052 <.do_clear_bss_start>: 52: a0 31 cpi r26, 0x10 ; 16 54: b2 07 cpc r27, r18 56: e1 f7 brne .-8 ; 0x50 <.do_clear_bss_loop> 58: 02 d0 rcall .+4 ; 0x5e
5a: 02 c0 rjmp .+4 ; 0x60 <_exit> 0000005c <__bad_interrupt>: 5c: d1 cf rjmp .-94 ; 0x0 <__vectors> 0000005e
: 5e: 50 d6 rcall .+3232 ; 0xd00 00000060 <_exit>: 60: f8 94 cli 00000062 <__stop_program>: 62: ff cf rjmp .-2 ; 0x62 <__stop_program>