Exemplo n.º 1
0
/* This function pulls intel hex formatted code from the serial port and loads 
   it into a temporary location. Once a complete SPM page length is stored,
   it executes a flash memory write.
    Return Error
	* ERR 1 - File upload synchronization is off (i.e. the ':' was not found)
	* ERR 2 - the checksum failed.

 */
char ihex_load(void)
{
    uint8_t
	i,temp_char,
	byte_count = 0,
	data_pairs,
	data_type,
	temp_byte,
	temp_store,
	address_lo,
	address_hi;

    unsigned int data; // temporary location to store program words
    
    unsigned long temp_address = 0ul;   //Tmp page fill address ??
	
	
    do
    {
	// Wait for characters 
	    do
		{
			temp_char = uart_read();
			if ( (temp_char == 13)  || (temp_char == 10))   // get and dispose of the CR or LF
					temp_char = 0;                           // Wait for first character of line
		} while (!temp_char);
	   if(temp_char != ':') // check to make sure the first character is ':'
	   {
	    return(1);
	   }

	
	/* get the count of data pairs */
 
	data_pairs  = get_hex_value();
	
	/* get the address to put the data */
	/* although we collect this data, we do not use it.  All data
	   programmed through this bootloader starts at application program
	   space location 0x0000. The collection is neccessary only for
	   the checksum calculation. */
	address_hi = get_hex_value();
	address_lo = get_hex_value();
	
	/* get the data type */
	data_type  = get_hex_value();
	
	temp_store = data_pairs + address_hi + address_lo + data_type;
	
	for( i = 0; i < data_pairs; i++ )
	{

		temp_byte = get_hex_value();		
	    page_data[byte_count] = temp_byte;	
		byte_count++;
	    temp_store += temp_byte;
	}
	    
	/* get the checksum */
    temp_byte = get_hex_value();
	

	

	/* check the data and checksum */
	if( (char)(temp_store + temp_byte) )
	{
	    return(2);
	}


	/* fill the rest of the page buffer with 0xFF if the last records are not 
	   a full page in length */
	if( data_type)   // End of File record 
	{
		
		for(byte_count; byte_count < SPM_PAGESIZE; byte_count++ )
	    {
			page_data[byte_count] = 0xFF;
	    }
	}

	/* if the page buffer is full, write the buffer to the temp flash buffer */
	if( byte_count >= SPM_PAGESIZE )
	{
	    byte_count = 0;

	    /* store data in temp buffer and write to flash */
	    for( i = 0; i < SPM_PAGESIZE; i += 2 )
	    {
		/* swap the bytes for little endian format */
		data = page_data[i];
		data |= ( page_data[ i + 1 ] << 8 );
		boot_page_fill( temp_address, data ); // call asm routine to load temporary flash buffer
		temp_address += 2; // select next word in temporary buffer
	    }

	    /* write to the flash */
	    boot_page_write( temp_address - SPM_PAGESIZE );
	    boot_spm_busy_wait();	
	    boot_rww_enable();				//Re-enable the RWW section
	    uart_write_char('*');
		// Display - characters 
		E_OUT_PORTA  =  0x73;  // Show P while programming 
		E_OUT_PB1(0);
		E_OUT_PB2(1);
	}
 
   } while( data_type != 1);            // Do while not end of File
	
	uart_write_char('E');                // End of file
    return(0);
}
Exemplo n.º 2
0
//Writes all the chars in buffer to the UART.
void uart_write_chars(const unsigned char* buffer, size_t size){
	for (size_t i = 0; i < size; i++){
		uart_write_char(buffer[i]);
	}
}
Exemplo n.º 3
0
/*--- MAIN -------------------------------------------------------------------*/
int main(void)
{
    uint8_t temp_char,tmp;
 	uint8_t bootFlag = TRUE;
    
    cli();
	
    /* the following code moves the interrupt vector pointer to the bootloader
       section. The problem is the compiler doesn't understand where to put
       the IV table. */
    GICR = _BV(IVCE);       
    GICR = _BV(IVSEL); //move interruptvectors to the Boot sector  ** WRITE 0 TO IVCE use = not |
   

// Initial 7 Segments on E_io
// Set direction of two switch to Input	
    DDRB =  0xFF;   // Output	
    DDRC  = 0x18;  // P3, P4 for  Control 7 segments Digits 

// Enable pull up resistor 
 	PORTC |= 0x24;

	
    /* The slow baud rate is required because of the intel hex parsing overhead.
       If I could figure out how to enable interrupts in the BLS (compiler issue)
       then a higher speed could be used by switching to an interrupt based
       UART ISR. The code could also be optimized. */
    
	uart_init( UART_INTERRUPT,UART_8_N_1,UART_38400);   
 
// poll USART receive complete flag 64k times to catch the 'i' reliably
 
// test if flash is empty (i.e. flash content is 0xff)
	if(pgm_read_byte_near(0x0000) != 0xFF) {
		bootFlag = FALSE; 
	}
	
//  Enter boot mode by press b 	
//	while (!(tmp  = uart_read()));
//	if (tmp == 'b')
//	     bootFlag = TRUE;
		 
// Check SW for enter boot mode either press both SW at the same time	
	tmp = PINC & (0x24);   // PB0, PB3 port
    if (!tmp)    // Press SW tmp = 0
        bootFlag = TRUE;	 
		 

	uart_write_str (VERSION);
// Display b characters 
	E_OUT_PORTA  =  0x7C;  // b
 	E_OUT_PB1(0);
 	E_OUT_PB2(1);
 
    
    /* this main loop is the user 'menu'. */
    while(bootFlag)                             
    {
			   
	if( (tmp = uart_read()) ) 
	{
 	   switch(tmp)
	   {
		case 'u': // download new program
		{
		    /* erase the main flash excepting BLS */
		    buf_address = 0; 
		    while ( APP_END > buf_address )
		    {
			boot_page_erase(buf_address);	// Perform page erase
			boot_spm_busy_wait();		// Wait until the memory is erased.
			buf_address += SPM_PAGESIZE;
		    }
		    buf_address = 0;

		    /* load new program */
			uart_write_str("READY \n");
		    if(( temp_char = ihex_load()))
		    {
				uart_write_str("ERR ");
				uart_write_char(temp_char + '0' );
				uart_write_char('\n');
		    }
		    else
			{
				bootFlag = FALSE ;  // Exit to run
			}
		}
		break;
		
		case 'x':                   //Exit upgrade
		{
			GICR = _BV(IVCE); 
			GICR &= ~(_BV(IVSEL) | _BV(IVCE)); //move interruptvectors to the Application sector  Write 0 to IVCE
		    jump_to_app(); // Jump to application sector
//		    wdt_enable(WDTO_15MS); // Enable Watchdog Timer to give reset
		}
		break;    
		default:
		{
		   uart_write_str(" u - Upload or x - Execute \n");
		}
	   } // end switch
	}  
    }	// end while(1)
// Start to application

	 GICR = _BV(IVCE); 
	 GICR &= ~(_BV(IVSEL) | _BV(IVCE)); //move interruptvectors to the Application sector  Write 0 to IVCE
	 jump_to_app(); // Jump to application sector

    return 0;
}