使用ATMEGA8A 自己制作ARDUINO全过程。

使用ATMEGA8A 自己制作ARDUINO全过程。,第1张

手上多余一大堆Mega8,最近刚好在熟悉ISP,想自己做一批来测试,重新写了Bootload,把代码贴出来给大家自己做,只用了512个字节,使用0x1c00开始地址作为Bootload地址,开机进入Bootload,10秒钟重启一次,如有有代码自动进入用户程序。
先上代码:

include <inttypes.h>
#include 
#include 
#include 
#include 
//#include 

//#define EEPROM 0
//FUCS FF D9 00 FF  0x1800
//FUCS FF DA 00 FF  0x1C00  OKOK

//#define F_CPU			16000000

/* We, Malmoitians, like slow interaction
 * therefore the slow baud rate ;-)
 */

//#define BAUD_RATE		9600

/* 6.000.000 is more or less 8 seconds at the
 * speed configured here
 */

//#define MAX_TIME_COUNT	6000000
#define MAX_TIME_COUNT (F_CPU>>1)
//#define MAX_TIME_COUNT_MORATORY	1600000

/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
#define HW_VER	 0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12

// AVR-GCC compiler compatibility
// avr-gcc compiler v3.1.x and older doesn't support outb() and inb()
//      if necessary, convert outb and inb to outp and inp
#ifndef outb
	#define outb(sfr,val)  (_SFR_BYTE(sfr) = (val))
#endif
#ifndef inb
	#define inb(sfr) _SFR_BYTE(sfr)
#endif

/* defines for future compatibility */
#ifndef cbi
	#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
	#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
#define eeprom_rb(addr)   eeprom_read_byte ((uint8_t *)(addr))
#define eeprom_rw(addr)   eeprom_read_word ((uint16_t *)(addr))
#define eeprom_wb(addr, val)   eeprom_write_byte ((uint8_t *)(addr), (uint8_t)(val))

/* Onboard LED is connected to pin PB5 */
#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PIND
#define LED      PIND5

#define SIG1	0x1E	// Yep, Atmel is the only manufacturer of AVR micros.  Single source :(
#define SIG2	0x93
#define SIG3	0x07
#define PAGE_SIZE	0x20U	//32 words

void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
#if 1

union address_union {
  uint16_t word;
  uint8_t  byte[2];
} address;

union length_union {
  uint16_t word;
  uint8_t  byte[2];
} length;
#endif
//uint16_t length;
//uint16_t address;

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 bootuart0=0,bootuart1=0;


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


void putch(char ch)
{
  /* m8 */
  while (!(inb(UCSRA) & _BV(UDRE)));
  outb(UDR,ch);
}

char getch(void)
{
  /* m8 */
	uint32_t count = 0;
  while(!(inb(UCSRA) & _BV(RXC))) {
		/* HACKME:: here is a good place to count times*/
		count++;
		//putch('.');
		if (count > MAX_TIME_COUNT){
			putch('!');
			app_start();
		}
  }
  return (inb(UDR));
}

void getNch(uint8_t count)
{
  uint8_t i;
  for(i=0;i<count;i++) {
    /* m8 */
    //while(!(inb(UCSRA) & _BV(RXC)));
    //inb(UDR);
		getch(); // need to handle time out
  }
}

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

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


int main(void)
{
  uint8_t ch,ch2;
  uint16_t w;

  //cbi(BL_DDR,BL);
  //sbi(BL_PORT,BL);

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

  /* 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 */
   // if(bit_is_set(BL_PIN,BL)) app_start();
  //}

  /* initialize UART(s) depending on CPU defined */
  /* 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

  //UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
  //UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
  //UCSRA = 0x00;
  //UCSRC = 0x86;
  //UCSRB = _BV(TXEN)|_BV(RXEN);


  /* this was giving uisp problems, so I removed it; without it, the boot
     works on with uisp and avrdude on the mac (at least). */
  putch(')';//uint32_t l;

  //uint32_t time_count;
  //time_count=0;
  /* set LED pin as output */

  //  sbi(LED_DDR,LED);
//		outb(LED_PORT, inb(LED_PORT) ^ _BV(LED));
//	for (i = 0; i < 16; i++) {
//		_delay_loop_2(0);
//	}
//for (l=0; l<40000000; l++)
	
	//outb(LED_PORT, inb(LED_PORT) ^= _BV(LED));
		/* flash onboard LED three times to signal entering of bootloader */

  //for(l=0; l<40000000; ++l);
  //for(i=0; i<3; ++i) {
    // sbi(LED_PORT,LED);
   //for(l=0; l<40000000; ++l);
    //
    //}
  /* see comment at previous call to putch() */

 //putch('//cbi(LED_PORT,LED); '); // this line is needed for the synchronization of the programmer
 /* forever */
for
  (
  ; ;)//sbi(LED_PORT,LED);	/* get character from UART */ {
 =
    //if((inb(UCSRA) & _BV(RXC))){
    getch
		ch ( );/* A bunch of if...else if... gives smaller code than switch...case ! *//* Hello is anyone home ? */
		
		if
	
		( 
		(=='P'ch)||(=='Q'ch)||(=='R'ch)||(=='0'ch))nothing_response( {
		  );if(
		  
		  == 'Q'ch)app_start();}/* 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
		( =='1'ch)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)=getch {
		  ch2 ( );if(
		  0x85 )ch2>getch( );nothing_response(
		  );}/* AVR ISP/STK500 board requests */
		else
	
		if
		( =='A'ch)=getch {
		  ch2 ( );if(
		  ==0x80ch2)byte_response( );HW_VER// Hardware versionelse		if
		  ( ==0x81ch2)byte_response( );SW_MAJOR// Software major versionelse	if
		  ( ==0x82ch2)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
		( =='B'ch)getNch( {
		  20);nothing_response(
		  );}/* Parallel programming stuff  DON'T CARE  */
		else
	
		if
		( =='E'ch)getNch( {
		  5);nothing_response(
		  );}/* Universal SPI programming command, disabled.  Would be used for fuses and lock bits.  */
		else


		if
		( =='V'ch)getNch( {
		  4);byte_response(
		  00);}/* Write memory, length is big endian and is in bytes  */
		else
	
		if
		( =='d'ch).[ {
		  length1byte]=getch ( );.[
		  length0byte]=getch( );.=
		  flags0eeprom ; if(
		  
		  getch ()=='E' ) .= flags1eeprom ; // putch(length);  for
		  
				  (
				  // putch(length>>8);
				   
		  = 0w;<.w;length++word)w[] {
		    buff=wgetch ( );// Store data in buffer, can't keep up with serial data stream whilst programming pages}	                        if
			
		  (

		  getch ()==0x20 )//	  					putch('W');# 
		  {
		ifdef
EERPOMif (
				. )flags//Write to EEPROM one byte at a timeeepromfor {		                (
					=0w;<.w;length++word)weeprom_wb( {
						.,address[word]buff)w;.++
						address;word}//		putch('E');
					}			
			else
				# else
if(					
. ==flags0eeprom)#endif					
//Write to FLASH one page at a time//else address_high = 0x00; 
					{ //if ((length.byte[0] & 0x01)) length++;	//Even up an odd number of bytes
					//if (address.byte[1]>127) address_high = 0x01;	//Only possible with m128, m256 will need 3rd address byte. FIXME
					//	putch('F');
			
					//address = address << 1;	        //address * 2 -> byte location
					#

				if

1cli (
					);//Disable interrupts, just to be sure//					sbi(PORTD,3);					//sbi(LED_PORT,LED);
while
					(
					bit_is_set(,)EECR)EEWE;//Wait for previous EEPROM writes to complete//				sbi(PORTD,3);			//cbi(LED_PORT,LED);
	asm
					volatile
					( "clr	r17		\n\t"//page_word_count
							 "lds	r30,address	\n\t"	//Address of FLASH location (in words)
							 
							 "lds	r31,address+1	\n\t"	"lsl   r30				\n\t"
							 "rol   r31				\n\t"
							 "ldi	r28,lo8(buff)	\n\t"  //address * 2 -> byte location
							 //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"	"sbrs r24,0		\n\t"
							 //Even up an odd number of bytes
							 
							 "rjmp length_loop		\n\t"  "adiw r24,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"	"rcall  wait_spm		\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"
							 "rcall  wait_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"	"rcall  wait_spm		\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
							 "rcall  wait_spm		\n\t"	//							 "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"
							 "rcall  wait_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"	"wait_spm:  \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_spm       \n\t"
							 "ret			\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
			   				
							 :	"=m"
							 ( ) :SPMCR"M" ( ) :PAGE_SIZE"r0" , "r16","r17","r24","r25","r28","r29","r30","r31");/* 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 */
			
					#
					endif
}//sbi(LED_PORT,LED);				

				//	sei();
				//				cbi(PORTD,3);
			putch
(
				0x14);putch(
				0x10);}}
			/* Set address, little endian. EEPROM in bytes, FLASH in words  */		
		/* This might explain why little endian was used here, big endian used everywhere else.  */
		else
		/* Perhaps extra address bytes may be added in future to support > 128kB FLASH.  */
		if
		( =='U'ch).[ {
		  address0byte]=getch ( );.[
		  address1byte]=getch();nothing_response(
		  );}/* Read memory block mode, length is big endian.  */
		else
		
		if
		( =='t'ch).[ {
		  length1byte]=getch ( );.[
		  length0byte]=getch ();#if
EERPOM		  if (
		  getch ()=='E' ) .= 
		  	flags1eeprom ; //0x45  EEPROMelse  #
		  else 
if(
		  getch ()=='F' ) #endif 
	
//0x46 FLASH.	
		  {                        =
				flags0eeprom ; .=
				address.word << address1word ; }if	        // address * 2 -> byte location
		  (

		  getch ()==0x20 ) // Command terminatorputch {		                (
			   0x14);for(

				= 0w;<.w ;length++word)w// Can handle odd and even lengths okay# {		        if
EERPOMif (
					. )flags// Byte access EEPROM readeepromputch {	                        (
								eeprom_rb(.)address)word;.++
						address;word}else
					# else 
if(					
. ==flags0eeprom)#endif
//if					
					{	
							(
						. <address0x1c00word)//if (!flags.rampz) putch
									{

										(
											pgm_read_byte_near(.)address)word;}else
									putch({
											0xff);}.
										++


						address;word}}
					putch
				(
				0x10);}}
		  /* Get device signature bytes  */
		else
	
		if
		( =='u'ch)if( {
		  getch ()==' ' ) putch( {
				0x14);putch(
				);SIG1putch(
				);SIG2putch(
				);SIG3putch(
				0x10);}}
		  /* Read oscillator calibration byte */
		else
	
		if
		( =='v'ch)byte_response( {
		  0x00);}//			time_count++;
		//				c();
//    } else {
//			}
//			if (time_count>=MAX_TIME_COUNT) {
//		}
//cbi(LED_PORT,LED);
}

	/* end of forever loop */
  } /* end of file ATmegaBOOT.c */
#



for



接下来是Makefile:

# Makefile . ATmegaBOOT
, E2004Lins- 10-14#program

. . name should not be changed.==
PROGRAM    # ATmegaBOOT

PRODUCTenteratmega8

for = the parameters - the UISP isp tool
ISPPARAMS  = -dprog=stk500 (dserial)$-SERIAL= 19200dspeed#=


:DIRAVR 2022 F-\-\AVR\miniuxAVR\arduino20090313lite\bin\win32\WinAVR=.
DIRAVR . /../..///bin-win3220090313WinAVR=(
DIRAVRBIN ) $/DIRAVR=(bin

DIRAVRUTILS ) $/DIRAVR/=utils(bin
DIRINC ) $/DIRAVR=(include
DIRLIB ) $/DIRAVR/=avr=lib


MCU_TARGET -- atmega8
LDSECTION  - =section.start=0x1C00text#=
0xdfFUSE_L     # =
0xcaFUSE_H     = 0xFF

FUSE_L     = 0xDD
FUSE_H     = (

ISPFUSES   ) $/DIRAVRBIN-=uisp (dpart)ATmega8 $--ISPPARAMS= (wr_fuse_l)$--FUSE_L= (wr_fuse_h)$=FUSE_H(
ISPFLASH   ) $/DIRAVRBIN-=uisp (dpart)ATmega8 $--ISPPARAMS-- iferase =upload ()$.PROGRAM-=hex (v


OBJ        ) $.PROGRAM=-o
OPTIMIZE   = -Os

DEFS       = 7372800DF_CPU-= 19200DBAUD_RATE==
LIBS       (

CC         ) $/DIRAVRBIN-#avr-gcc


. Override is only needed by avr=lib build system-

override CFLAGS        - (g )Wall $-OPTIMIZE= (mmcu)$-MCU_TARGET( )D$(PRODUCT) $-DEFS( )I$=DIRINC-
override LDFLAGS       , -Wl,(Map)$.PROGRAM,(map)$=LDSECTION(

OBJCOPY        ) $/DIRAVRBIN-=avr(objcopy
OBJDUMP        ) $/DIRAVRBIN-=avr(objdump
SIZE           ) $/DIRAVRBIN-:avr(size

all) $.PROGRAMasm:elf lst text ( size

isp) $.PROGRAM()hex
	$(ISPFUSES)
	$(ISPFLASH)

$.PROGRAM:(elf) $(OBJ)
	$(CC) $(CFLAGS) $-LDFLAGS^ (o $@ $) $:LIBS-

clean*
	rm .rf -*s
	rm .rf *.o -*elf
	rm .rf *.lst asm:map

() $.PROGRAM%.s

:%s. ()c
	$-CC( )S $-CFLAGS^ :g1 $(

lst)  $.PROGRAM%.lst

:%lst. ()elf
	$-OBJDUMP- <h :S $( > $@

size) $.PROGRAM()hex
	$^SIZE# $for

. Rules : building the :text rom images

text( hex bin srec

hex)  $.PROGRAM:(hex
bin)  $.PROGRAM:(bin
srec) $.PROGRAM%.srec

:%hex. ()elf
	$-OBJCOPY. -j .text -j <data %O ihex $. $@

:%srec. ()elf
	$-OBJCOPY. -j .text -j <data %O srec $. $@

:%bin. ()elf
	$-OBJCOPY. -j .text -j <data O binary $ $@

然后使用 make 编译出hex

用烧录器烧录或者ISP

配置位如图:


下载完代开Arduino


开发板选择 Arduino NG or older
处理器 Atmega8
编程器选择 STK500

这样使用 19200下载到开发板就可以了!

在Arduino\hardware\arduino\avr目录下有个broads.txt

由于我使用的是7.372800 19200BPS这里面需要改动

##############################################################

atmegang.name=Arduino NG or older

atmegang.upload.tool=avrdude
atmegang.upload.protocol=arduino
atmegang.upload.speed=19200

atmegang.bootloader.tool=avrdude
atmegang.bootloader.unlock_bits=0x3F
atmegang.bootloader.lock_bits=0x0F

atmegang.build.mcu=atmegang
atmegang.build.f_cpu=7372800L
atmegang.build.board=AVR_NG
atmegang.build.core=arduino
atmegang.build.variant=standard

Arduino NG or older w/ ATmega168 --------------------------------

atmegang.menu.cpu.atmega168=ATmega168

atmegang.menu.cpu.atmega168.upload.maximum_size=14336
atmegang.menu.cpu.atmega168.upload.maximum_data_size=1024

atmegang.menu.cpu.atmega168.bootloader.low_fuses=0xff
atmegang.menu.cpu.atmega168.bootloader.high_fuses=0xdd
atmegang.menu.cpu.atmega168.bootloader.extended_fuses=0xF8
atmegang.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex

atmegang.menu.cpu.atmega168.build.mcu=atmega168

Arduino NG or older w/ ATmega8 ------------------------------

atmegang.menu.cpu.atmega8=ATmega8

atmegang.menu.cpu.atmega8.upload.maximum_size=7168
atmegang.menu.cpu.atmega8.upload.maximum_data_size=1024

atmegang.menu.cpu.atmega8.bootloader.low_fuses=0xdf
atmegang.menu.cpu.atmega8.bootloader.high_fuses=0xca
atmegang.menu.cpu.atmega8.bootloader.extended_fuses=0xF8
atmegang.menu.cpu.atmega8.bootloader.file=atmega8/ATmegaBOOT-prod-firmware-2009-11-07.hex

atmegang.menu.cpu.atmega8.build.mcu=atmega8

##############################################################
这样就完成了。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/733559.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-27
下一篇2022-04-27

发表评论

登录后才能评论

评论列表(0条)

    保存