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

Po raz kolejny Bootloader atmega32 czytałem wszystkie posty

bluebit2 14 Gru 2010 00:21 2439 5
  • #1 8866007
    bluebit2
    Poziom 11  
    Witam,

    Możecie spojrzeć na ten kod (poniżej?)

    Problem jest taki że co bym nie robił zdarza się w niektórych wsadach że jakaś strona pamięci zostaje zapisana samymi 0xFF. (wgrywam wsad potem sprawdzam programatorem poprawność).

    Procesor Atmega32;
    4mhz (RC);
    UART 9600

    
    
    ////////////////////////////////////////////////////////////////////////////////
    /* Dołączenie bibliotek */
    ////////////////////////////////////////////////////////////////////////////////
    
    /* biblioteki avr-libc */
    #include <stdint.h>
    #include <avr/boot.h>
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    #include <avr/wdt.h>
    #include <util/delay.h>
    #include <util/setbaud.h>
    #include "hardef.h"
    #include "delay.h"
    #include "lcd.h"
    
    ////////////////////////////////////////////////////////////////////////////////
    /* Definicje stałych programowych i makr */
    ////////////////////////////////////////////////////////////////////////////////
    
    /* czas przesyłania jednego znaku przez UART [us] */
        #define UART_BYTE_TIME ( F_CPU / ( BAUD / ( 1 + 8 + 1 ) ) )
    
    	#define UART_BAUD	9600	   	//prędkość transmisji
    	#define UART_CONST	(F_CPU/(16ul*UART_BAUD)-1)
    	
    	
    /* makro zamieniające podany argument na łańcuch znaków */
    	#define TOSTRING( x ) STRINGIFY( x )
    	#define STRINGIFY( x ) #x
    ////////////////////////////////////////////////////////////////////////////////
    /* Deklaracje funkcji statycznych */
    ////////////////////////////////////////////////////////////////////////////////
    
    static void UART_TX_Byte(const uint8_t Data );
    
    static void UART_TX_String_P(const prog_char *String_Ptr );
    
    static uint8_t _UART_RX_Wait(uint16_t Timeout );
    
    /* Makro przeliczające argument w milisekundach na przyjmowaną przez funkcję 
     * _UART_RX_Wait wielokrotność czasu przesyłania jednego znaku. */
    #define UART_RX_Wait( x ) _UART_RX_Wait( ( x * 1000UL ) / UART_BYTE_TIME )
    
    
    ////////////////////////////////////////////////////////////////////////////////
    /* Definicje funkcji */
    ////////////////////////////////////////////////////////////////////////////////
    
    static void __vectors(void )
    __attribute__ (( section( ".vectors" ), naked, used ));
    	
    static void __vectors(void )
    {
        /* skok do sekcji .init2 (konieczny ze względu na umieszczanie stałych z 
         * pamięci programu pomiędzy sekcjami .vectors a .init0, a więc na samym 
         * początku programu w przypadku wykorzystania opcji -nostartfiles */
        asm (
            "rjmp __init2" "\n\t"
            : : );
    }
    
    
    
    static void __init2(void )
    __attribute__ (( section( ".init2" ), naked, used ));
    
    
    static void __init2(void )
    {
        /* inicjalizacja wskaźnika stosu, rejestru z zerem i rejestru flag */
    	asm volatile (
    		"out __SP_L__, %A0" "\n\t"
    		"out __SP_H__, %B0" "\n\t"
    		"clr __zero_reg__" "\n\t"
    		"out __SREG__, __zero_reg__" "\n\t"
            : : "r"( ( uint16_t )( RAMEND ) ) );
    }
    
    
    #ifdef WDIF
        static void __init3(void )
            __attribute__ (( section( ".init3" ), naked, used ));
    		
    		
        static void __init3(void )
        {
            /* wyłączenie watchdoga (w tych mikrokontrolerach, w których watchdog 
             * ma możliwość generowania przerwania pozostaje on też aktywny po 
             * resecie) */
            MCUSR = 0;
            _WD_CONTROL_REG = 1 << _WD_CHANGE_BIT | 1 << WDE;
            _WD_CONTROL_REG = 0;
        }
    	
    	
    #endif
    
    static void __init9(void )
        __attribute__ (( section( ".init9" ), naked, used ));
    static void __init9(void )
    {
        /* skok do funkcji main */
    	asm (
    		"rjmp main" "\n\t"
            : : );
    }
    
    
    
    
    
    int main(void )
        __attribute__ (( noreturn ));
    	
    	
    	
    	
    int main(void )	
    {
    //guzik
    	DDRD&=~(1<<3);
    	PORTD|=(1<<3);	
    //zasilanie	
    	DDRB |= 1<<1;
    	PORTB &= ~(1<<1);
    	
    	
    
    
    	if ( (((PIND>>3)&0x01)==1)){
    	
    	//jesli nie zostal nacisniety drugi guzik to idziemy do programu
    	/* skok do właściwego programu */
    	
        #ifdef __AVR_HAVE_JMP_CALL__
            asm volatile ( 
                "jmp 0" "\n\t"
                : : );
        #else
            asm volatile ( 
                "clr r30" "\n\t"
                "clr r31" "\n\t"
                "ijmp" "\n\t"
                : : );
        #endif
        
    	}else{
    		DDRB |= 1<<1;
    		PORTB |= 1<<1;
    	}
    	
    	delayms8(10);	
    	LCDinit();
    	LCDcls();
    	LCDstr("Update SW");
    	
    
    	
        /* konfiguracja i włączenie interfejsu UART */
     	UBRRH = (unsigned char)((UART_CONST>>8));
    	UBRRL = (unsigned char)(UART_CONST);
    	UCSRA=0;
    	//wlanczamy odbiornik i nadajnik
    
    	//ustawiamy ramke 8n1 
    
    	UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
    	UCSRB = (1<<RXEN)|(1<<TXEN);
    	
    	
    	
        /* deklaracja zmiennych */
        uint8_t Retries_Left, Received_Char;
    	uint8_t msb,lsb,upgrade,CRCodb,typodp;
    	uint16_t CRC;
    	
        
        /* wysyłanie znaku '?' do odebrania znaku 'u' lub upłynięcia czasu 
         * oczekiwania */
    	for ( Retries_Left = BOOT_WAIT * 10; Retries_Left > 0; 
            --Retries_Left )
    	{
            if ( ( Received_Char = UART_RX_Wait( 100 ) ) == 'u' )
                break;
            
    		UART_TX_Byte( '?' );
    	}
    	
    	
    	
        if ( Received_Char == 'u' )
        {
    
            Retries_Left = 10;
            while ( 1 )
            {
                /* odebranie znaku */
                Received_Char = UART_RX_Wait( 1500 );
    			
               if ( Received_Char == 'w' )
                {
    				UART_TX_Byte( '&' );
    				msb=UART_RX_Wait( 1000 );
    				lsb=UART_RX_Wait( 1000 );
    				eeprom_write_byte(20,msb);			
    				eeprom_write_byte(21,lsb);
    				typodp=0;
    			
                    /* odczekanie do zakończenia operacji na pamięci EEPROM 
                     * i Flash */
                    eeprom_busy_wait();
                    boot_spm_busy_wait();
                    
                    /* kasowanie całej pamięci programu */
                    for ( uint32_t Page_Address = 0; Page_Address < BLS_START; 
                        Page_Address += SPM_PAGESIZE )
                    {
                        /* skasowanie strony pamięci */
                        boot_page_erase( Page_Address );
                        boot_spm_busy_wait();
                    }
                    
                    /* programowanie pamięci programu */
                    for ( uint32_t Page_Address = 0; Page_Address < BLS_START; 
                        Page_Address += SPM_PAGESIZE )
                    {
                        /* wysłanie znaku '+' */
                        if(typodp==0){
    						UART_TX_Byte( '+' );
    					}else{					
    						UART_TX_Byte( '^' );
    					}
    				
    				
                        /* jeśli odebrano zero lub upłynął czas oczekiwania na 
                         * odpowiedź, to zakończenie pracy bootloadera */
                        if ( !UART_RX_Wait( 500 ) )
                            break;
                        
                        /* zapełnienie bufora strony */
    					CRC=0;
    					
    					
                        for ( uint16_t Byte_Address = 0; 
                            Byte_Address < SPM_PAGESIZE; Byte_Address += 2 )
                        {
                            /* przygotowanie instrukcji */
    						msb=UART_RX_Wait( 300 );
    						CRC+=msb;
                            uint16_t Instruction = ( uint16_t )msb;
    						
    						
    						msb=UART_RX_Wait( 300 );
    						CRC+=msb;
                            Instruction += msb<< 8;
    						
                            
                            /* zapisanie instrukcji do bufora */
                            boot_page_fill( Byte_Address, Instruction );
                        }
    					
    					if ( CRCodb=UART_RX_Wait( 1000 ) ){
    						if(CRCodb==(CRC&0x00ff)){ //jesli odebralismy sume kontrolną i sie zgadza
    						
    							/* zapisanie strony pamięci */
    							
    													
    							boot_page_write( Page_Address );
    							boot_spm_busy_wait();
    							
    							typodp=0;
    						
    						}else{
    							Page_Address -= SPM_PAGESIZE;	//odejmujemy
    							typodp=1;
    						}
    					
    					}
    					
                        
    
                    }
                    
                    /* odblokowanie sekcji Read-While-Write */
                    boot_rww_enable();
                    
                    /* zakończenie pracy bootloadera */
                    
    				break;
    				
                }
                else if ( Received_Char == 'q' || !Retries_Left-- )
                {
                    /* jeśli odebrano znak 'q' lub upłynął czas oczekiwania na 
                     * odpowiedź, to zakończenie pracy bootloadera */
                    break;
                }
            }
        }
        
        /* wyłączenie interfejsu UART (dzieje się to dopiero po zakończeniu 
         * wysyłania) i odczekanie do końca ewentualnej transmisji */
    	UCSRB = 0;
    	
        _delay_us( UART_BYTE_TIME );
    
    	DDRB |= 1<<1;
    	PORTB &= ~(1<<1);
    	
    			
    				
        /* nieskończona pętla (konieczna, by kompilator nie wygenerował 
         * niepotrzebnego kodu) */
        while ( 1 )
            {}
    }
    
    static void UART_TX_Byte(const uint8_t Data ){
    
    	UCSRB &= ~(1 << RXEN);
    
    	while ( !( UCSRA & 1 << UDRE ) )
            {}
        
    	UDR = Data;
    	
    	
    	_delay_us( UART_BYTE_TIME );	
    	UCSRB |= (1 << RXEN);
    		
    }
    
    static void UART_TX_String_P(const prog_char *String_Ptr ){
    	uint8_t Single_Char;
        
    	while ( ( Single_Char = pgm_read_byte( String_Ptr++ ) ) )
            UART_TX_Byte( Single_Char );
    }
    
    
    
    static uint8_t _UART_RX_Wait(uint16_t Timeout ){
    	do
        {
    		if ( UCSRA & 1 << RXC )
            return UDR;
            
            _delay_us( UART_BYTE_TIME );
    	} while ( Timeout-- );
        
    	return 0;
    }
    
  • #3 8866394
    bluebit2
    Poziom 11  
    Program do wgrywania wsadu pisałem sam, jest w C++,

    interfejs podłączenia UART jest jedno przewodowy stąd fikuśne wysyłanie znaku na magistrale (z blokowaniem odbioru).

    Wszystko jest ok, tylko tyle że niekiedy zaprogramuje mi się cała strona flash z wypełnionymi 0xFF, i co dziwne w przypadku tego samego wsadu zawsze jest to to samo miejsce.
  • #4 8866677
    mirekk36
    Poziom 42  
    tak gwoli ścisłości, kod do procka, który wykorzystujesz jest wprost zassany z innego źródła, wprowadzasz tylko swoje modyfikacje. Wprawdzie kod jest otwarty i full FREE to jednak wypadałoby jeśli już cytujesz całość dołączyć i posługiwać się także nagłówkiem

    ////////////////////////////////////////////////////////////////////////////////
    /* Bootloader
     * Autor: Mirosław Kardaś (2009-06-16)
     * Modyfikacje: Paweł Szramowski (2009-06-30) */
    ////////////////////////////////////////////////////////////////////////////////


    bo inaczej to tak trochę nie ładnie.

    A swoją drogą jeśli chcesz stosować tylko 1 przewodową transmisję to nie dziw się, że masz takie problemy w tym konkretnym przypadku. Przecież tu widać jak na dłoni po co są te dane przesyłane zwrotnie do PC. Nie tylko "tak sobie" żeby było ładnie, ale głównie po to, żeby PC wiedział kiedy może zacząć przesyłać kolejną część. To jest ważne, bo sam proces programowania trochę przecież trwa prawda? Więc musiałbyś powprowadzać w swoim programie na PC jakieś sztuczne i dosyć długi Timeouty. A żeby to działało ci uniwersalnie później z każdym prockiem to na prawdę musiałyby być długi żeby przewidzieć różne czasy zapisu - przecież różne procki mają różną długość strony do zapisu więc może on różnie trwać. To z kolei spowoduje, że taki twój bootloader zacznie duuuużo wolnie wgrywać wsad do procka ale jeśli to nie jest dla ciebie jakimś krytycznym parametrem i masz czas na kawę - to oczywiście nie będzie to problemem i program na PC zadziała.

    Gorzej natomiast okaże się w przypadku chęci zastosowania Bluetooth'a - który z natury rzeczy sam przesyła dane pakietowo i sam wprowadza opóźnienia. Wtedy to już zrobi ci się makabryczny ślimak przy takim podejściu.
  • #5 8866701
    LordBlick
    VIP Zasłużony dla elektroda
    bluebit2 napisał:
    Wszystko jest ok, tylko tyle że niekiedy zaprogramuje mi się cała strona flash z wypełnionymi 0xFF, i co dziwne w przypadku tego samego wsadu zawsze jest to to samo miejsce.
    Nie ma takiej możliwości - 0xFF jest wartością po Chip Erase proszę sobie sprawdzić swoim programatorem. Programowanie polega na zapisie innej wartości, czyli po prostu problem polega na niezapisaniu strony.
  • #6 8867826
    bluebit2
    Poziom 11  
    w woli ścisłości,

    mirekk36
    magistrala jest dupex-owa, więc nie muszę wprowadzać timeout-ów,
    jedno przewodowa half-duplex.

    pozatym kod faktycznie jest Mirosław Kardaś chodz mocno modyfikowany i jak się dobrze przyjrzeć to podobny do przykładów AVR (czyżby autor nieładnie nie zaznaczył że wzorował się na przykładach - oj nie ładnie)

    Light-I
    dzięki za rzeczową odpowiedz :)
REKLAMA