2

Author Topic: Bootloader development  (Read 2116 times)

0 Members and 1 Guest are viewing this topic.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Bootloader development
« on: July 31, 2008, 10:10:06 AM »
I need a bootloader that can connect to bluetooth.

I saw that the Arduino BT advertises that it can upload sketches wirelessly via bluetooth, but I can't find any documentation on how that works. I was however able to find their BT bootloader source code in their SVN repository.

I am using an ATmega168, which that bootloader supports.

I want to know what is it in that bootloader code that deals with bluetooth.

The bootloader I have been using (fast tiny & mega) doesn't  connected to my BlueSMiRF. It blinks red, goes green for a second, and then back to blinking red.

Here is the source code for the Arduino BT bootloader:

http://svn.berlios.de/viewcvs/arduino/trunk/hardware/bootloaders/bt/ATmegaBOOT_168.c?view=markup

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: Bootloader development
« Reply #1 on: August 01, 2008, 01:09:31 PM »
I've managed to cut their code in half because I am making it for an atmega168. but I can't get it to compile...i need help with a makefile.

heres the code:
Code: [Select]


/* some includes */
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>               


#define set_output(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define set_input(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))


#define high(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define low(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))




/* the current avr-libc eeprom functions do not support the ATmega168 */
/* own eeprom write/read functions are used instead */
#ifndef __AVR_ATmega168__
#include <avr/eeprom.h>
#endif

/* define F_CPU according to AVR_FREQ set in Makefile */
/* Is there a better way to pass such a parameter from Makefile to source code ? */

#define F_CPU     8000000

#include <util/delay.h>


/* 20060803: hacked by DojoCorp */
/* set the waiting time for the bootloader */
#define MAX_TIME_COUNT (F_CPU>>1)

/* set the UART baud rate */
/* 20060803: hacked by DojoCorp */
#define BAUD_RATE   57600


/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
/* never allow AVR Studio to do an update !!!! */
#define HW_VER   0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x0f


/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
/* other ATmegas have only one UART, so only one pin is defined to enter bootloader ?????????????????????????????*/
#define BL_DDR  DDRD
#define BL_PORT PORTD
#define BL_PIN  PIND
#define BL      PIND6


/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
/* if monitor functions are included, LED goes on after monitor was entered */
#define LED_DDR  DDRD
#define LED_PORT PORTD
#define LED_PIN  PIND
#define LED      PIND4




/* define various device id's */
/* manufacturer byte is always the same */
#define SIG1    0x1E    // Yep, Atmel is the only manufacturer of AVR micros.  Single source :(

#if defined __AVR_ATmega8__
#define SIG2    0x93
#define SIG3    0x07
#define PAGE_SIZE       0x20U   //32 words

#elif defined __AVR_ATmega168__
#define SIG2    0x94
#define SIG3    0x06
#define PAGE_SIZE       0x40U   //64 words
#endif


/* function prototypes */
void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
char gethex(void);
void puthex(char);
void flash_led(uint8_t);

/* some variables */
union address_union {
    uint16_t word;
    uint8_t  byte[2];
} address;

union length_union {
    uint16_t word;
    uint8_t  byte[2];
} length;

struct flags_struct {
    unsigned eeprom : 1;
    unsigned rampz  : 1;
} flags;

uint8_t buff[256];
uint8_t address_high;

uint8_t pagesz=0x80;

uint8_t i;
uint8_t bootuart = 0;

void (*app_start)(void) = 0x0000;


/* main program starts here */
int main(void)
{
    uint8_t ch,ch2;
    uint16_t w;

    asm volatile("nop\n\t");

    /* set pin direction for bootloader pin and enable pullup */
    BL_DDR &= ~_BV(BL);
    BL_PORT |= _BV(BL);



    /* check if flash is programmed already, if not start bootloader anyway */
    if(pgm_read_byte_near(0x0000) != 0xFF) {


        /* check if bootloader pin is set low */
        /* we don't start this part neither for the m8, nor m168 */
        //if(bit_is_set(BL_PIN, BL)) {
    //      app_start();
    //    }
    }



    /* initialize UART(s) depending on CPU defined */       
#ifdef __AVR_ATmega168__ 
        UBRR0H = ((F_CPU / 16 + BAUD_RATE / 2) / BAUD_RATE - 1) >> 8;
        UBRR0L = ((F_CPU / 16 + BAUD_RATE / 2) / BAUD_RATE - 1);


    //UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
    //UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
    UCSR0B = (1<<RXEN0) | (1<<TXEN0);
    UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
#elif defined __AVR_ATmega8__
  /* m8 */
  UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8;        // set baud rate
  UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
  UCSRB = (1<<RXEN)|(1<<TXEN);  // enable Rx & Tx
  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // config USART; 8N1
#endif

    /* set LED pin as output */
    LED_DDR |= _BV(LED);
             

     
      set_output(DDRD,PIND7);
          high(PORTD,PD7);   
          for (i = 0; i < 16; i++) {
                 
                        _delay_loop_2(0);
          }
       
       
          low(PORTD,PD7);


    /* flash onboard LED to signal entering of bootloader */
    flash_led(3);


   //message("SET BT PAGEMODE 3 2000 1");    ???????????????????????????????????????
putch('S');
putch('E');
putch('T');
putch(' ');
putch('B');
putch('T');
putch(' ');
putch('P');
putch('A');
putch('G');
putch('E');
putch('M');
putch('O');
putch('D');
putch('E');
putch(' ');
putch('3');
putch(' ');
putch('2');
putch('0');
putch('0');
putch('0');
putch(' ');
putch('1');
putch(0x0D);

 
          //put_s("SET BT ROLE 0 f 7d00"); 
        putch('S');
        putch('E');
        putch('T');
        putch(' ');
        putch('B');
        putch('T');
        putch(' ');
        putch('R');
        putch('O');
        putch('L');
        putch('E');
        putch(' ');
        putch('0');
        putch(' ');
        putch('f');
        putch(' ');
        putch('7');
        putch('d');
        putch('0');
        putch('0');
        putch(0x0D);






    /* forever loop */
    for (;;) {

        /* get character from UART */
        ch = getch();

        /* A bunch of if...else if... gives smaller code than switch...case ! */

        /* Hello is anyone home ? */
        if(ch=='0') {
            nothing_response();
        }


        /* Request programmer ID */
        /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry  */
        /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares.  */
        else if(ch=='1') {
            if (getch() == ' ') {
                putch(0x14);
                putch('A');
                putch('V');
                putch('R');
                putch(' ');
                putch('I');
                putch('S');
                putch('P');
                putch(0x10);
            }
        }


        /* AVR ISP/STK500 board commands  DON'T CARE so default nothing_response */
        else if(ch=='@') {
            ch2 = getch();
            if (ch2>0x85) getch();
            nothing_response();
        }


        /* AVR ISP/STK500 board requests */
        else if(ch=='A') {
            ch2 = getch();
            if(ch2==0x80) byte_response(HW_VER);                // Hardware version
            else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
            else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
            else if(ch2==0x98) byte_response(0x03);             // Unknown but seems to be required by avr studio 3.56
            else byte_response(0x00);                           // Covers various unnecessary responses we don't care about
        }


        /* Device Parameters  DON'T CARE, DEVICE IS FIXED  */
        else if(ch=='B') {
            getNch(20);
            nothing_response();
        }


        /* Parallel programming stuff  DON'T CARE  */
        else if(ch=='E') {
            getNch(5);
            nothing_response();
        }


        /* Enter programming mode  */
        else if(ch=='P') {
            nothing_response();
        }


        /* Leave programming mode  */
        else if(ch=='Q') {
            nothing_response();
        }


        /* Erase device, don't care as we will erase one page at a time anyway.  */
        else if(ch=='R') {
            nothing_response();
        }


        /* Set address, little endian. EEPROM in bytes, FLASH in words  */
        /* Perhaps extra address bytes may be added in future to support > 128kB FLASH.  */
        /* This might explain why little endian was used here, big endian used everywhere else.  */
        else if(ch=='U') {
            address.byte[0] = getch();
            address.byte[1] = getch();
            nothing_response();
        }


        /* Universal SPI programming command, disabled.  Would be used for fuses and lock bits.  */
        else if(ch=='V') {
            getNch(4);
            byte_response(0x00);
        }


        /* Write memory, length is big endian and is in bytes  */
        else if(ch=='d') {
            length.byte[1] = getch();
            length.byte[0] = getch();
            flags.eeprom = 0;
            if (getch() == 'E') flags.eeprom = 1;
            for (w=0;w<length.word;w++) {
                buff[w] = getch();                              // Store data in buffer, can't keep up with serial data stream whilst programming pages
            }
            if (getch() == ' ') {
                if (flags.eeprom) {                             //Write to EEPROM one byte at a time
                    for(w=0;w<length.word;w++) {
#ifdef __AVR_ATmega168__
                        while(EECR & (1<<EEPE));
                        EEAR = (uint16_t)(void *)address.word;
                        EEDR = buff[w];
                        EECR |= (1<<EEMPE);
                        EECR |= (1<<EEPE);
#else
                        eeprom_write_byte((void *)address.word,buff[w]);
#endif
                        address.word++;
                    }                   
                }
                else {                                          //Write to FLASH one page at a time
                    if (address.byte[1]>127) address_high = 0x01;       //Only possible with m128, m256 will need 3rd address byte. FIXME
                    else address_high = 0x00;

                    address.word = address.word << 1;           //address * 2 -> byte location
                    /* if ((length.byte[0] & 0x01) == 0x01) length.word++;      //Even up an odd number of bytes */
                    if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
                    cli();                                      //Disable interrupts, just to be sure
                        // HACKME: EEPE used to be EEWE
                    while(bit_is_set(EECR,EEPE));                       //Wait for previous EEPROM writes to complete
                    asm volatile(
                                 "clr   r17             \n\t"   //page_word_count
                                 "lds   r30,address     \n\t"   //Address of FLASH location (in bytes)
                                 "lds   r31,address+1   \n\t"
                                 "ldi   r28,lo8(buff)   \n\t"   //Start of buffer array in RAM
                                 "ldi   r29,hi8(buff)   \n\t"
                                 "lds   r24,length      \n\t"   //Length of data to be written (in bytes)
                                 "lds   r25,length+1    \n\t"
                                 "length_loop:          \n\t"   //Main loop, repeat for number of words in block                                                                                                                 
                                 "cpi   r17,0x00        \n\t"   //If page_word_count=0 then erase page
                                 "brne  no_page_erase   \n\t"                                           
                                 "wait_spm1:            \n\t"
                                 "lds   r16,%0          \n\t"   //Wait for previous spm to complete
                                 "andi  r16,1           \n\t"
                                 "cpi   r16,1           \n\t"
                                 "breq  wait_spm1       \n\t"
                                 "ldi   r16,0x03        \n\t"   //Erase page pointed to by Z
                                 "sts   %0,r16          \n\t"
                                 "spm                   \n\t"                                                   

                                 "wait_spm2:            \n\t"
                                 "lds   r16,%0          \n\t"   //Wait for previous spm to complete
                                 "andi  r16,1           \n\t"
                                 "cpi   r16,1           \n\t"
                                 "breq  wait_spm2       \n\t"                                                                   

                                 "ldi   r16,0x11        \n\t"   //Re-enable RWW section
                                 "sts   %0,r16          \n\t"                                                                   
                                 "spm                   \n\t"

                                 "no_page_erase:                \n\t"                                                   
                                 "ld    r0,Y+           \n\t"   //Write 2 bytes into page buffer
                                 "ld    r1,Y+           \n\t"                                                   
                                                         
                                 "wait_spm3:            \n\t"
                                 "lds   r16,%0          \n\t"   //Wait for previous spm to complete
                                 "andi  r16,1           \n\t"
                                 "cpi   r16,1           \n\t"
                                 "breq  wait_spm3       \n\t"
                                 "ldi   r16,0x01        \n\t"   //Load r0,r1 into FLASH page buffer
                                 "sts   %0,r16          \n\t"
                                 "spm                   \n\t"
                                                         
                                 "inc   r17             \n\t"   //page_word_count++
                                 "cpi r17,%1            \n\t"
                                 "brlo  same_page       \n\t"   //Still same page in FLASH
                                 "write_page:           \n\t"
                                 "clr   r17             \n\t"   //New page, write current one first
                                 "wait_spm4:            \n\t"
                                 "lds   r16,%0          \n\t"   //Wait for previous spm to complete
                                 "andi  r16,1           \n\t"
                                 "cpi   r16,1           \n\t"
                                 "breq  wait_spm4       \n\t"
                                                                                                           
                                 "ldi   r16,0x05        \n\t"   //Write page pointed to by Z
                                 "sts   %0,r16          \n\t"
                                 "spm                   \n\t"

                                 "wait_spm5:            \n\t"
                                 "lds   r16,%0          \n\t"   //Wait for previous spm to complete
                                 "andi  r16,1           \n\t"
                                 "cpi   r16,1           \n\t"
                                 "breq  wait_spm5       \n\t"                                                                   
                                 "ldi   r16,0x11        \n\t"   //Re-enable RWW section
                                 "sts   %0,r16          \n\t"                                                                   
                                 "spm                   \n\t"                                                   

                                 "same_page:            \n\t"                                                   
                                 "adiw  r30,2           \n\t"   //Next word in FLASH
                                 "sbiw  r24,2           \n\t"   //length-2
                                 "breq  final_write     \n\t"   //Finished
                                 "rjmp  length_loop     \n\t"
                                 "final_write:          \n\t"
                                 "cpi   r17,0           \n\t"
                                 "breq  block_done      \n\t"
                                 "adiw  r24,2           \n\t"   //length+2, fool above check on length after short page write
                                 "rjmp  write_page      \n\t"
                                 "block_done:           \n\t"
                                 "clr   __zero_reg__    \n\t"   //restore zero register
#ifdef  __AVR_ATmega168__
                                 : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#else
                                 : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#endif
                                 );
                    /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
                    /* exit the bootloader without a power cycle anyhow */
                }
                putch(0x14);
                putch(0x10);
            }           
        }
   

        /* Read memory block mode, length is big endian.  */
        else if(ch=='t') {
            length.byte[1] = getch();
            length.byte[0] = getch();

            if (getch() == 'E') flags.eeprom = 1;
            else {
                flags.eeprom = 0;
                address.word = address.word << 1;               // address * 2 -> byte location
            }
            if (getch() == ' ') {                               // Command terminator
                putch(0x14);
                for (w=0;w < length.word;w++) {                 // Can handle odd and even lengths okay
                    if (flags.eeprom) {                         // Byte access EEPROM read
#ifdef __AVR_ATmega168__
                        while(EECR & (1<<EEPE));
                        EEAR = (uint16_t)(void *)address.word;
                        EECR |= (1<<EERE);
                        putch(EEDR);
#else
                        putch(eeprom_read_byte((void *)address.word));
#endif
                        address.word++;
                    }
                    else {

                        if (!flags.rampz) putch(pgm_read_byte_near(address.word));

                        address.word++;
                    }
                }
                putch(0x10);
            }
        }


        /* Get device signature bytes  */
        else if(ch=='u') {
            if (getch() == ' ') {
                putch(0x14);
                putch(SIG1);
                putch(SIG2);
                putch(SIG3);
                putch(0x10);
            }
        }


        /* Read oscillator calibration byte */
        else if(ch=='v') {
            byte_response(0x00);
        }



    }
    /* end of forever loop */

}



char gethex(void) {
    char ah,al;

    ah = getch(); putch(ah);
    al = getch(); putch(al);
    if(ah >= 'a') {
        ah = ah - 'a' + 0x0a;
    } else if(ah >= '0') {
        ah -= '0';
    }
    if(al >= 'a') {
        al = al - 'a' + 0x0a;
    } else if(al >= '0') {
        al -= '0';
    }
    return (ah << 4) + al;
}


void puthex(char ch) {
    char ah,al;

    ah = (ch & 0xf0) >> 4;
    if(ah >= 0x0a) {
        ah = ah - 0x0a + 'a';
    } else {
        ah += '0';
    }
    al = (ch & 0x0f);
    if(al >= 0x0a) {
        al = al - 0x0a + 'a';
    } else {
        al += '0';
    }
    putch(ah);
    putch(al);
}


void putch(char ch)
{
#ifdef __AVR_ATmega168__
    while (!(UCSR0A & _BV(UDRE0)));
    UDR0 = ch;
#else
    /* m8,16,32,169,8515,8535,163 */
    while (!(UCSRA & _BV(UDRE)));
    UDR = ch;
#endif
}


char getch(void)
{
#ifdef __AVR_ATmega168__
    uint32_t count = 0;
    while(!(UCSR0A & _BV(RXC0))){
        /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
        /* HACKME:: here is a good place to count times*/
        count++;
        if (count > MAX_TIME_COUNT)
                app_start();
     }
    return UDR0;
#else
    /* m8,16,32,169,8515,8535,163 */
    uint32_t count = 0;
    while(!(UCSRA & _BV(RXC))){
        /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
        /* HACKME:: here is a good place to count times*/
        count++;
        if (count > MAX_TIME_COUNT)
                app_start();
     }
    return UDR;
#endif
}


void getNch(uint8_t count)
{
    uint8_t i;
    for(i=0;i<count;i++) {
#ifdef __AVR_ATmega168__
        while(!(UCSR0A & _BV(RXC0)));
        UDR0;
#else
        /* m8,16,32,169,8515,8535,163 */
        /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/               
        //while(!(UCSRA & _BV(RXC)));
        //UDR;
    uint8_t i;
    for(i=0;i<count;i++) {
        getch(); // need to handle time out
    }
#endif         
    }
}


void byte_response(uint8_t val)
{
    if (getch() == ' ') {
        putch(0x14);
        putch(val);
        putch(0x10);
    }
}


void nothing_response(void)
{
    if (getch() == ' ') {
        putch(0x14);
        putch(0x10);
    }
}

void flash_led(uint8_t count)
{
    /* flash onboard LED three times to signal entering of bootloader */
    uint32_t l;

    if (count == 0) {
      count = 3;
    }
   
    for (i = 0; i < count; ++i) {
        LED_PORT |= _BV(LED);
        for(l = 0; l < (2 * F_CPU); ++l);
        LED_PORT &= ~_BV(LED);
        for(l = 0; l < (F_CPU / 5); ++l);
    }
}


/* end of file ATmegaBOOT.c */


Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: Bootloader development
« Reply #2 on: August 05, 2008, 02:09:15 PM »
its going to be based off of uart.h and xmodem.h, so you can upload the hex-to-bin files via hyperterminal.

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,659
  • Helpful? 169
    • Society of Robots
Re: Bootloader development
« Reply #3 on: August 09, 2008, 08:29:51 AM »
What compile errors you getting?

You can use my makefile from the $50 Robot.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: Bootloader development
« Reply #4 on: August 09, 2008, 12:00:39 PM »
Yeah after looking around a bit i learned that your makefile is pretty much the standard avrlib 'template' makefile

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: Bootloader development
« Reply #5 on: August 10, 2008, 02:12:50 AM »
bahh i've spent all day trying different bootloaders that use xmodem and I can't get anything to work  >:(


Here is the simplest looking one, but It fails to upload after timing out.
Code: [Select]
#include <inttypes.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/boot.h>
#include <setjmp.h>
#include "uart.h" // include uart function librar


#define BAUD 57600



#if SPM_PAGESIZE > 128
#define DATA_BUFFER_SIZE SPM_PAGESIZE
#else
#define DATA_BUFFER_SIZE SPM_PAGESIZE
#endif


#define XMODEM_NUL 0x00
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_EOF 0x1A


#define XMODEM_RECIEVING_WAIT_CHAR 'C'



void (*app)(void)=0;

void initialize(void)

{


    uartInit();  // initialize the UART (serial port)

uartSetBaudRate(BAUD);// set the baud rate of the UART for our debug/reporting output




/* Set frame format: 8data, 2stop bit */

//UCSR0C = (1<<USBS0)|(3<<UCSZ00);

//INIT THE TIMER0 AS THE FREE RUN FOR AUTO

TIMSK0=TIMSK0&(~(1<<TOIE0));//MASK THE TIMER0 OVERFLOW INTERRUPT

    TCNT0=0;//SET THE TIMER0 COUNT TO ZERO

    TCCR0B = 1<<CS00;//set the source clk for timer0 as the main clock

}



int

uart_putchar(char c)

{

loop_until_bit_is_set(UCSR0A, UDRE0);

UDR0 = c;

return 0;

}



int uart_getchar(void)

{

unsigned char status, resh, resl;

/* no data to be received */

if( !(UCSR0A & (1<<RXC0)) )

return -1;

/* Get status and ninth bit, then data */

/* from buffer */

status = UCSR0A;

resh = UCSR0B;

resl = UDR0;

/* If error, return -1 */

if ( status & ((1<<FE0)|(1<<DOR0)|(1<<UPE0)))

return -1;

/* Filter the ninth bit, then return */

//resh = (resh >> 1) & 0x01;

return resl;

}



int uart_waitchar(void)

{

int c;

while((c=uart_getchar())==-1);

return c;

}



int calcrc(unsigned char *ptr, int count)

{

int crc;

char i;

crc = 0;

while (--count >= 0)

{

crc = crc ^ (int) *ptr++ << 8;

i = 8;

do

{

if (crc & 0x8000)

crc = crc << 1 ^ 0x1021;

else

crc = crc << 1;

} while(--i);

}

return (crc);

}

const char startupString[]="press key 'd' to download,press other key to execute the application\n\r\0";



int main(void)

{

int i,j;

unsigned char timercount=0;

unsigned char packNO;

unsigned long address;

unsigned long bufferPoint;

unsigned char data[DATA_BUFFER_SIZE];

unsigned int crc;

initialize();

//fdevopen(uart_putchar,uart_getchar,0);

i=0;

while(startupString[i]!='\0')

{

uart_putchar(startupString[i]);

i++;

}

if(uart_waitchar()!='d')app();

while(uart_getchar()!=XMODEM_SOH)

{

if(TIFR0&(1<<TOV0))

{

if(timercount==200)

{

uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);

timercount=0;

}

timercount++;

TIFR0=TIFR0|(1<<TOV0);

}

}

packNO=1;

address=0;

bufferPoint=0;

do

{

if(packNO==(char)uart_waitchar())

{

if(packNO==(unsigned char)(~uart_waitchar()))

{

for(i=0;i<128;i++)

{

data[bufferPoint]=(unsigned char)uart_waitchar();

bufferPoint++;

}

crc=0;

crc+=(uart_waitchar()<<8);

crc+=uart_waitchar();

if(calcrc(&data[bufferPoint-128],128)==crc)

{

while(bufferPoint>=SPM_PAGESIZE)

{



boot_page_erase(address);

while(boot_rww_busy())

    {

            boot_rww_enable();

        }

for(i=0;i<SPM_PAGESIZE;i+=2)

            {

            boot_page_fill(address%SPM_PAGESIZE,data[i]+(data[i+1]<<8));

      address+=2;

      }

        boot_page_write(address-1);

        while(boot_rww_busy())

        {

            boot_rww_enable();

        }

for(j=0;i<bufferPoint;i++,j++)

{

data[j]=data[i];

}

bufferPoint=j;

}

uart_putchar(XMODEM_ACK);

packNO++;

}

else

{

uart_putchar(XMODEM_NAK);

}

}

}

else

{

uart_putchar(XMODEM_NAK);

}

}while(uart_waitchar()!=XMODEM_EOT);

uart_putchar(XMODEM_ACK);

(app)();

}


 


Get Your Ad Here

data_list