;; Org is set at 0 so that there is no padding before the sled. ;; This code should be run from RAM; the address doesn't really matter. BASE == 0x0 .org BASE code_size_guess == 0xB2 LED_PORT = 0x0200 FLASH_LED = 0x02 FAIL_LED = 0x04 ;; MSP430f5510 definitions FCTL1 == 0x0140 FCTL3 == 0x0144 BUSY == 0x0001 FWPW == 0xA500 ERASE == 0x0004 WRT == 0x0040 BLKWRT == 0x0080 WAIT == 0x0008 LOCK == 0x0010 ;; Format of payload: (all values MSP-endian) ;; { ;; number of blocks: 1 byte ;; checksum: 1 byte (byte such that two's complement sum of payload bytes == 0xff) ;; repeat: (total of (payload length - 3) bytes) ;; (start_address >> 8): 2 bytes ;; block data: 512 bytes ;; } ;; The shortest possible payload would thus be <<0x00 0xFF>> ;; A payload that writes 0's to 0xFE00-0xFFFF would be: ;; <<0x01 0x00 0xFE 0x00 0x00*512>> ;; Assumptions/caveats: ;; 1) Assume RAM is in low memory. It will fail miserably otherwise ;; 2) All this code is very carefully written to be position-independent ;; Register usage: ;; ;; r4: start of payload ;; r5: address of start start: ;; the next two instructions must be the first two instructions after start mov r0, r5 add #(code_size_guess + start - .), r5 mov r6, r4 bis.b #FLASH_LED+FAIL_LED, &LED_PORT+4 bic.b #FLASH_LED+FAIL_LED, &LED_PORT+2 ;; calc checksum ;; local regs: ;; r6: running sum ;; r7: end addr ;; r8: current addr ;; r9: scratch mov r4, r8 mov r4, r7 mov.b @r8, r9 incd r7 rla r9, 1 ; Add r9*514 (r9<<1 + r9 << 9) add r9, r7 rla r9, 8 add r9, r7 add @r8, r7 mov.b #0, r6 1: add.b @r8+, r6 cmp r7, r8 jlo 1b cmp #0xff, r6 bis.b #FAIL_LED, &LED_PORT+2 reta ;; Get flashing ;; local regs: ;; r6: current src ;; r7: current dest ;; r8: block id ;; r9: block count ;; r10: dwords remaining mov r4, r6 clr r8 mov.b @r4, r9 incd r6 next_block: dec r9 jnc done_programming bis #FLASH_LED, &LED_PORT+2 ;; calc dest addr mov @r6+, r7 rlam.a #4, r7 ; multiply by 256 to recover real address rlam.a #4, r7 ;; erase block 1: bit #BUSY, &FCTL3 jnz 1b mov #FWPW, &FCTL3 mov #FWPW+ERASE, &FCTL1 clr @r7 1: bit #BUSY, &FCTL3 jnz 1b ;; not sure whether I need to bounce LOCK here mov #32, r10 mov #FWPW+BLKWRT+WRT, &FCTL1 2: mov @r6+, 0(r7) mov @r6+, 2(r7) 3: bit #WAIT, &FCTL3 jz 3b add #4, r7 ; This was originally 2 incd insns dec r10 jnz 2b mov #FWPW, &FCTL1 4: bit #BUSY, &FCTL3 jnz 4b mov #FWPW+LOCK, &FCTL3 jmp next_block done_programming: bic.b #FLASH_LED, &LED_PORT+2 bic.b #FAIL_LED, &LED_PORT+2 bsl_ret: mov #2, r12 mov #0xDEAD, r13 mov #0xBEEF, r14 bra #0x1002 payload: .data .if (payload-start) != code_size_guess .print "Payload guess wrong" .endif