int main(void) { char c; unsigned char idx[4] = {0, 0, 0, 0}; unsigned char port, total_ports = 2, valid_ports = 0x3; volatile unsigned long i, j; int ret = 0; u32union delay; RCONbits.SWDTEN = 0; /* 70 MIPS; 140MHz */ CLKDIVbits.PLLPRE = 0; PLLFBDbits.PLLDIV = 74; CLKDIVbits.PLLPOST = 0; /* switch clock to FRC oscillator with PLL */ __builtin_write_OSCCONH(1); __builtin_write_OSCCONL(OSCCON | 1); /* wait for clock switch to complete */ while (OSCCONbits.OSWEN == 1); /* wait for PLL lock */ while (OSCCONbits.LOCK != 1); ANSELA = 0; ANSELB = 0; ANSELC = 0; TRIS_LED = 0; LED = 0; /* detect hw revision */ /* set RB1 internal pull down */ _TRISB1 = 1; _CNPDB1 = 1; /* hw 0v5 has RB1 connected to RB4 */ _TRISB4 = 0; _LATB4 = 0; for (i = 0; i < 100000; i++); j = (_RB1 & 1); _LATB4 = 1; for (i = 0; i < 100000; i++); j |= ((_RB1 & 1) << 1); if (j == 0b10) { hw_rev = 0x05; } else { /* set RB9 internal pull down */ _TRISB9 = 1; _CNPDB9 = 1; /* set RA9 internal pull down */ _TRISA9 = 1; _CNPDA9 = 1; ANSELBbits.ANSB1 = 1; AD1CON3bits.ADCS = 16; AD1CON2bits.CHPS = 2; AD1CON1bits.ADON = 1; AD1CHS0bits.CH0SA = 3; AD1CON1bits.SAMP = 1; for (i = 0; i < 1000; i++); AD1CON1bits.SAMP = 0; for (i = 0; i < 10000; i++); if (ADC1BUF0 > 400) /* hw 0v4 has 1.25V vref on AN3 */ hw_rev = 0x04; else if (_RB9 == 1) /* hw 0v3 has external pull-up on RB9 */ hw_rev = 0x03; else if (_RA9 == 1) /* hw 0v2 has RB9 floating and RA9 pull-up */ hw_rev = 0x02; else /* hw 0v1 has RA9 and RB9 floating */ hw_rev = 0x01; _CNPDB9 = 0; _CNPDA9 = 0; AD1CON1bits.ADON = 0; } _CNPDB1 = 0; _TRISB4 = 1; /* weak pull up on serial port rx pins */ if (hw_rev >= 0x05) { _CNPUB12 = 1; _CNPUB15 = 1; _CNPUC7 = 1; _CNPUB7 = 1; } else if (hw_rev >= 0x03) { _CNPUB11 = 1; _CNPUB6 = 1; _CNPUB2 = 1; _CNPUB13 = 1; } else { _CNPUB6 = 1; _CNPUA4 = 1; } if (hw_rev >= 0x03) { total_ports = 4; valid_ports = 0xf; } /* get devid */ read_flash(0xff0000, &devid); delay.l = BOOT_DELAY; if (delay.b[0] == 0) goto_usercode(); /* Timer setup */ /* increments every instruction cycle */ T2CONbits.T32 = 1; /* clear timer3 IF */ IFS0bits.T3IF = 0; /* disable timer3 isr */ IEC0bits.T3IE = 0; /* Convert seconds into timer count value */ delay.l = ((unsigned long) (FCY)) * ((unsigned long) (delay.b[0])); PR3 = delay.w[1]; PR2 = delay.w[0]; TMR3HLD = 0x0000; TMR2 = 0x0000; T2CONbits.TON = 1; uart_init(); while (1) { for (port = 0; port < total_ports; port++) { if (valid_ports & (1 << port)) { used_port = port; if (get_char(&c)) { if (c != magic_word_bin[idx[port]]) valid_ports &= ~(1 << port); else idx[port]++; if (idx[port] == (sizeof(magic_word_bin)-1)) { ret = 1; break; } } } } if (valid_ports == 0) ret = 0xff; if (_T3IF == 1) { ret = 0xff; } if (ret) break; } T2CONbits.TON = 0; LED = 1; if (ret == 0xff) { put_char('*'); goto_usercode(); } put_str((char*) msg); put_str((char*) msg_bin); load_bin(); return 0; }
void load_bin(void) { unsigned char c; int ret; u32union page_addr; unsigned int crc, rcrc, i; for (i = 0; i < PAGE_SIZE; i++) page[i].b[3] = 0xff; while (1) { /* request page */ /* 3 bytes - msb first */ page_addr.b[3] = 0; ret = get_char((char*) &page_addr.b[2]); ret |= get_char((char*) &page_addr.b[1]); ret |= get_char((char*) &page_addr.b[0]); if (page_addr.l == 0x00ffffff) { put_char('e'); break; } else { put_char('p'); } page_addr.l &= ~((PAGE_SIZE << 1)-1); if ( ((page_addr.l >= BOOT_FLASH_START_ADDR) && (page_addr.l < BOOT_FLASH_END_ADDR)) || (page_addr.l == DEV_CONFIG_PAGE_ADDRESS) ) { put_char('s'); continue; } else { put_char('d'); } /* load page to sram */ ret = 0; crc = 0; for (i = 0; i < PAGE_SIZE; i++) { ret |= get_char((char*) &c); crc += c; page[i].b[2] = c; ret |= get_char((char*) &c); crc += c; page[i].b[1] = c; ret |= get_char((char*) &c); crc += c; page[i].b[0] = c; } /* get crc */ put_char('c'); rcrc = 0; ret |= get_char((char*) &c); rcrc = c << 8; ret |= get_char((char*) &c); rcrc |= c; if (rcrc != crc) { ret = 100; put_char('x'); } if (ret) break; erase_page(page_addr.l); put_char('e'); /* protect bootloader start addr */ if (page_addr.l == 0) { page[0].l = 0x040800; page[1].l = 0x000000; } for (i = 0; i < PAGE_SIZE/2; i++) { write_dword(page_addr.l + i*4, page[i*2].l, page[i*2 + 1].l); } put_char('w'); } if (ret) { put_char('X'); while (1); } else { put_char('K'); goto_usercode(); } }