logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ATMega128 i bootloader. Program odbiera dane z portu, ale nie zapisuje we flashu

neemo 01 Sty 2009 15:15 1998 2
REKLAMA
  • #1 5932827
    neemo
    Poziom 11  
    Witam serdecznie wszystkich w nowym roku.
    Mam problem z bootloaderm napisanym w GCC. Zasada jego działania jest następująca: po resecie przez sekundę ma skanować port szeregowy i jeśli nadejdzie znak "0xaa" to rozpoczyna odbieranie paczek po 256bajtów i zapisuje je do FLASH'u. Kod źródłowy jest następujący:

    #include <avr/io.h>
    #include <avr/boot.h>
    #include <avr/pgmspace.h>
    
    #define PROG_START 0x0000
    #define BUFSIZE 256
    
    #define TIMER1STR {TCCR1B=4; TCNT1=0;}
    #define TIMER1STP TCCR1B=0;
    
    #define BootStr 0xf800;
    
    unsigned char buf[BUFSIZE];
    unsigned char booterr;
    unsigned long int FlashAddr;
    unsigned int bufptr, pagptr;
    
    //zapis strony pamięci do Flash'a
    void write_one_page(unsigned char *buf)
    {
      boot_page_erase(FlashAddr);                  			//wykasowanie strony Flash
      boot_spm_busy_wait();									//czeka aż apmięć zostanie wykasowana
      for(pagptr = 0; pagptr < SPM_PAGESIZE; pagptr += 2) 	//zapis danych do bufora we Flash'u
      {
        boot_page_fill(pagptr, buf[pagptr] + (buf[pagptr + 1] << 0x8));
      }
      boot_page_write(FlashAddr);                  //zapis bufora do strony pamięci
      boot_spm_busy_wait();                        //czeka aż byfor zostanie zapisany
    }
    
    //wyjście z bootloadera do sekcji programu
    void QuitBoot()
    {
      boot_rww_enable();                           //włączenie kodu aplikacji
      (*((void(*)(void))PROG_START))();            //skok pod adres PROG_START
    }
    
    //wysłanie bajtu do COMa
    void WriteCom(unsigned char dat)
    {
    	while (!( UCSR0A & (1<<UDRE0)));
    	UDR0 = dat;
    	while (!( UCSR0A & (1<<UDRE0)));
    }
    
    //odebranie bajdu z portu COM
    //timeout ustawiony na 1s
    //ustawia pierwszy bit w booterr jeśli wystąpi timeout
    unsigned char ReadCom(void)
    {
    	TIMER1STR;
    
    	while (!(UCSR0A & (1<<RXC0)))
    	{
    		if(TIFR&(1<<TOV1)) {booterr|=1; return 0;}
    	};
    	return UDR0;
    }
    
    int main(void)
    {
    	//inicjacja portu COM0
    	UBRR0L = 3;   //protokˇ- 500000bps
    	UBRR0H = 0;
    	UCSR0A = 2;
       	UCSR0B = 0x18;
    	UCSR0C = 0x06;
    	//inicjajca TIMERA1
    	TCCR1A = 0;
    	//konfiguracja portów procesora
    	DDRA = 0; 
    	DDRB = 0x80;
    	DDRC = 0;
    	DDRD = 0;
    	DDRE = 0;
    	DDRF = 0;
    	DDRG = 0;
    	PORTB = 0x80;
    	//konfiguracja zmiennych
    	booterr=0;
    	//program główny bootloadera
    	if(ReadCom()!=0xaa)
    			QuitBoot();
    	else
    	{
    		unsigned int crcRd,adrBuf,crc,i;
    		unsigned char tmp;
    		WriteCom(0xab);
    		while(ReadCom()==10)
    		{
    			crc=tmp=ReadCom();
    			adrBuf=(tmp<< 0x8);
    			crc+=tmp=ReadCom();
    			adrBuf|=tmp;
    			for(i=0; i<BUFSIZE; i++)
    			{
    				crc+=buf[i]=ReadCom();
    			}
    			crcRd=(ReadCom()<< 0x8);
    			crcRd|=ReadCom();
    			if((0xffff-crc)==crcRd)
    			{
    				FlashAddr = adrBuf;
    				write_one_page(buf);
    				WriteCom(0xdd);
    			}
    			else
    				QuitBoot();
    		}
    		QuitBoot();
    	}
    	return 0;
    }

    Program został skompilowany z dyrektywą linkera: -Wl,-section-start=.text=0xf800.
    Fuse'y: BOOTSZ1=0, BOOTSZ0=1, BOOTRST=0.
    Program odbiera dane z portu ale nie zapisuje ich do Flas'u. Bardzo proszę o wszelkie sugestie bo nie mam już pojęcia co może być nie tak.
  • REKLAMA
  • #2 5934378
    kemot55
    Poziom 31  
    Możesz skorzystać z gotowca np. "CV Megaload". Na http://www.microsyl.com/
    są kody źródłowe (oczywiście tylko, żeby podpatrzeć jak to robią inni :-)).
    Ja wzorowałem się na tym co napisali w dokumentacji do procesora (procedurę zapisu dla ATMEGA128 napisałem dokładnie tak w przykładzie).
  • #3 5935570
    neemo
    Poziom 11  
    Po długiej walce problem rozwiązany: trzeba skompilować program z dyrektywą: -Wl,-section-start=.text=0x1f000, czyli program bootloadera musi się zaczynać od adresu 0xf800*2=1f000.
REKLAMA