/***************************************************** This program was produced by the CodeWizardAVR V2.05.3a Standard Automatic Program Generator © Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Version : Date : 1/25/2012 Author : J. De Wit Company : Sjelab DS Comments: Chip type : ATmega644P Program type : Boot Loader - Size:512words AVR Core Clock frequency: 16.000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 1024 *****************************************************/ #include #include // Instellingen SPI voor SD kaart #define SPI_DI PORTB.6 //MISO Data Output MMC/SD-Kaart #define SPI_DO PORTB.5 //MOSI Data Input MMC/SD-Kaart #define SPI_Clock PORTB.7 //Clock MMC/SD-Kaart #define MMC_Chip_Select PORTB.4 //Chip Select MMC/SD-Kaart #define ETH_Chip_Select PORTB.3 //Chip Select Ethernet Controler // Display #define CNTR_ENABLE PORTD.4 // Enable display #define CNTR_RW PORTD.6 // R/W display #define CNTR_RS PORTD.7 // RS display #define Clear_LCD LCD_commando(0x01) // Clear LCD voert commando 01 uit clear LCD scherm. #define LCD_cursorOn LCD_commando(0x0F) // disply on / cursor on / cursor pos. blinks on #define LCD_cursorOff LCD_commando(0x0C) // disply on / cursor off / cursor pos. blinks off #define LCD_regel2 LCD_commando(0xC0) // Regel 2 is adres 0x40 gevolgt door LCD_commando or 0x80 #define LCD_regel3 LCD_commando(0x94) // Regel 3 is adres 0x14 gevolgt door LCD_commando or 0x80 #define LCD_regel4 LCD_commando(0xD4) // Regel 4 is adres 0x54 gevolgt door LCD_commando or 0x80 #define LED_GROEN_F1 PORTB.0 #define LED_GEEL_F2 PORTB.1 #define LED_ROOD_F3 PORTB.2 // Crystal Oscillator division factor: 1 #pragma optsize- //CLKPR=0x80; //CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif //Block Size in Bytes #define BlockSize 512 #define VBR_Addr 0x1C6 //FAT12 and FAT16 Structure Starting at Offset 36 #define BS_DrvNum 36 //Fysieke drive nummer 1bit Deze waarde is gerelateerd aan de BIOS waarde voor het volgnummer van de fysieke disk. Floppies krijgen de waarde 0x00, en de fysieke harddisks worden geïdentificeerd met 0x80. Deze waarde wordt ingesteld vóórdat een INT 13 BIOS aanroep specificeert welk apparaat moet worden benaderd. Deze waarde is alleen relevant als van dit volume geboot wordt. #define BS_Reserved1 37 //Gereserveerd 1bit Altijd 0 #define BS_BootSig 38 //Extended Boot Signature 1bit Moet voor XP altijd de waarde 0x28 of 0x29 hebben #define BS_VolID 39 //Volume Serie Nummer 4bit Een willekeurig serienummer welke tijdens het formatteren wordt gecreëerd om het volume te kunnen identificeren. #define BS_VolLab 43 //Volume label 11bit Werd ooit gebruikt voor het label van het volume. Het label is nu een speciale ingang in de FAT. #define BS_FilSysType 54 //Filesystem type 8bit Wordt niet gebruikt door Windows. Bevat "FAT12 ", "FAT16 " of "FAT ". #asm .equ SPMCSR =0x37; #endasm struct BootSec { unsigned char BS_jmpBoot[3]; //0xEB 0x00 0x90 char BS_OEMName[8]; //De OEM identificatie 8 bytes Hiermee wordt de naam en het versienummer van het OS aangegeven welke gebruikt werd voor het formatteren. (B.v. MSDOS5.0) unsigned int BPB_BytesPerSec; //Bytes/sector 2byte Is meestal 512. Maar 1024, 2046, of 1096 zijn ook geldige waarden unsigned char BPB_SecPerClus; //Sectors/cluster 1byte Op een FAT16 volume kunnen maar 65.524 clusters worden benut. Grote volumes worden daarom ondersteund door het aantal sectoren per cluster te verhogen. Geldige waarden zijn 1, 2, 4, 8, 16, 32, 64 en 128. unsigned int BPB_RsvdSecCnt; //gereserveerde sectors 2byte Het aantal sectoren vóórdat de eerste FAT volgt. Dat is meestal 1 (de bootsector). unsigned char BPB_NumFATs; //Aantal FAT's 1byte Het aantal kopieën van de FAT op dat volume. Meestal 2. unsigned int BPB_RootEntCnt; //Root Entries 2bytes Het aantal ingangen van de FAT voor de Root van dat volume. Elke ingang is 32 bytes voor een file of een folder. Voor de root is dit standaard 512. Één ingang wordt gebruikt voor het volume label. unsigned int BPB_TotSec16; //Small Sectors 2bytes Het aantal sectoren als dat minder is dan 65.536 (16 bits). Is het aantal groter dan is deze waarde 0 en wordt "Large sectors" gebruikt. unsigned char BPB_Media; //Media Descriptor 1byte Geeft het soort medium aan: 0xF8 = harddisk 0xF0 = 3,5 inch high density floppy (Wordt door XP niet meer gebruikt) unsigned int BPB_FATSz16; //Sectors/FAT 2byte Geeft de omvang van de FAT aan. Deze waarde wordt onder andere gebruikt om te bepalen waar de root-directory en de data op het volume beginnen. unsigned int BPB_SecPerTrk; //Sectors/Track 2byte Onderdeel van de geometrie van de disk. Wordt verkregen bij een low-level format. unsigned int BPB_NumHeads; //Aantal heads 2byte Onderdeel van de geometrie van de disk. Wordt verkregen bij een low-level format. unsigned long BPB_HiddSec; //Verborgen sectors 4bytes Het aantal sectoren vóór de boot sector. Deze waarde wordt onder andere gebruikt om te bepalen waar de root-directory en de data op het volume beginnen. unsigned long BPB_TotSec32; //Large sectors 4bytes Als "small sectors" 0 is, dan bevat dit veld het aantal sectoren (32bits). Als "Small sectors" niet 0 is dan is dit veld 0. }; struct DirEntry { unsigned char DIR_Name[11]; //8 chars filename unsigned char DIR_Attr; //file attributes RSHA, Longname, Drive Label, Directory unsigned char DIR_NTRes; //set to zero unsigned char DIR_CrtTimeTenth; //creation time part in milliseconds unsigned int DIR_CrtTime; //creation time unsigned int DIR_CrtDate; //creation date unsigned int DIR_LastAccDate; //last access date unsigned int DIR_FstClusHI; //first cluster high word unsigned int DIR_WrtTime; //last write time unsigned int DIR_WrtDate; //last write date unsigned int DIR_FstClusLO; //first cluster low word unsigned long DIR_FileSize; }; struct FileStatus { unsigned int SectorPointer; //Wijst naar de in de buffer geladen sector in de cluster, dus niet de absolute sector unsigned int DataPointer; //Wijst naar de byte in de buffer unsigned int cluster; //Geeft het volgende cluster aan volgens de FAT unsigned int startcluster; //Geeft het eerste cluster aan char EndOfFile; //Is normaal 0, maar wordt 1 zodra het einde van de file bereikt is char FileOpen; //Is 1 als de file geopend is in Read mode en 2 in Write mode unsigned long File_Size; //Geeft de grote van de file aan in bytes unsigned long ByteCnt; //Wijst naar de byte in de file char Filename[13]; //Bevat de naam van de geopende file unsigned int RootEntrie; //Bevat de gegevens entrie in de rootsector unsigned int WrtTime; //last write time unsigned int WrtDate; //last write date }; struct Disk_info { unsigned char OK; // Geeft aan of de Sd kaart OK is unsigned char ClusterSize; //Cluster Size unsigned int RootRecord; //begin adres root directory unsigned int RootOffset; //Offset adres t.o.v. root directory. Geeft het root adres van een directory aan. unsigned int FirstDataSector; //begin adres data directory unsigned int BootRecordAdress; //Volume Boot Record Address unsigned int FATOffset; //FAT_OFFSET unsigned int AantalFATsector; //Aantal FAT sectoren. } DiskInfo; static struct FileStatus MMCfile; static char MMCBuffer[BlockSize]; // blocksize is ingesteld op 512 static unsigned int SectorPointer; //,FilePointer; // Geeft een pointer aan naar de MMC kaart record. signed int LCDentrieCnt,LCDRootsectorCnt; const char strBootloader[]="bootloader"; const char strSDcardOK[]="SD card OK"; const char strSDcardERROR[]="SD card ERROR"; void FlashProgram(void); void DO_SPM(int data, int adres); void ERASE_PAGE(int adres); void WRITE_PAGE(int adres); void BLBset(void); //Zendt Routine een Byte naar de SD kaart void Write_Byte_MMC (unsigned char Byte) { SPDR = Byte; while(!(SPSR & 0x80)) {}; //wacht tot SPIF = 1 } //ontvang Routine een Byte van de MMC-Kaart unsigned char Read_Byte_MMC (void) { unsigned char Byte = 0; SPDR = 0xff; while(!(SPSR & 0x80)){}; //wacht tot SPIF = 1 Byte = SPDR; return (Byte); } //zendt een Commando naar de MMC/SD-Kaart unsigned char Write_Command_MMC (unsigned char *CMD) { unsigned char readbyte = 0xff; unsigned char Timeout = 0; unsigned char cnt; //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) MMC_Chip_Select=1; // MMC_Disable(); //sendet 8 Clock Impulse Write_Byte_MMC(0xFF); //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv) MMC_Chip_Select=0; // MMC_Enable() //sendet 6 Byte Commando for (cnt = 0;cnt<0x06;cnt++) Write_Byte_MMC(*CMD++); //sendet 6 Byte Commando zur MMC/SD-Karte //Wacht op een juist antwoord van de MMC/SD-Karte while (readbyte == 0xff) { readbyte = Read_Byte_MMC(); if (Timeout++ > 100) { break; //Abbruch da die MMC/SD-Karte nicht Antwortet } } return(readbyte); } //Lees Routine void MMC_Read_Block(unsigned char *CMD,unsigned char *Buffer,unsigned int Bytes) { unsigned int cnt; //Zent Commando CMD naar de MMC/SD-Kaart if (Write_Command_MMC (CMD) != 0) return; //Wacht op de start byte van de MMC/SD-Kaart (FEh/Start Byte) while (Read_Byte_MMC() != 0xfe){}; //Lees het Bolk aantal Bytes van MMC/SD-Karte for (cnt=0;cnt>24 ); CMD[2] = ((addr & 0x00FF0000) >>16 ); CMD[3] = ((addr & 0x0000FF00) >>8 ); MMC_Read_Block(CMD,MMCBuffer,512); return(0); } //Installatie routine MMC/SD-Kaart (SPI-MODE) unsigned char mmc_init () { unsigned int cnt,Timeout = 0; static unsigned char CMD[6]={0x40,0x00,0x00,0x00,0x00,0x95}; struct BootSec *bootp; //Pointer op Bootsector Struktuur //Voor de SD kaart geactiveerd dient te worden moet het volgende worden ingesteld en uitgevoerd. Dit meenemen in het begin van de MAIN // MMC/CD kaart configureren op de poort waarop deze is aangesloten. MMC_Chip_Select=1; // disable MMC //Power ON (Insersion) //After supply voltage reached 2.2 volts, wait for a millisecond at least, // set DI and CS high and apply more than 74 pulses to SCLK and the card will able to accept a native command. for (cnt = 0;cnt<0x10;cnt++) Write_Byte_MMC(0xff); //Zendt Commando CMD0 an MMC/SD-Kaart {0x40,0x00,0x00,0x00,0x00,0x95} // GO_IDLE_STATE Reset all cards to Idle State while(Write_Command_MMC (CMD) !=1) { if (Timeout++ > 500) return(1); //Afbreking commando 0 kaart reageerd niet (Return Code1) else delay_us(10); } //Zendt Commando CMD1 naar de MMC/SD-Kaart {0x41,0x00,0x00,0x00,0x00,0xFF}; //SEND_OP_COND Ask all cards in idle state to send their operation conditions register content in the response on the CMD line. Timeout = 0; CMD[0] = 0x41;//Commando 1 CMD[5] = 0xFF; while( Write_Command_MMC (CMD) !=0) { if (Timeout++ > 1000) return(2); //Afbreking commando 1 kaart reageerd niet (Return Code2) else delay_ms(1); } // SD?MMC kaart is OK SPI snelheid gaat omhoog en kaart data wordt uitgelezen. // SPSR = 1; // SPI2X geset voor dubbele snelheid. //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) MMC_Chip_Select=1; // disable MMC //Uitlezen Master Boot Record van de MMC/SD Kaart allereerste sector van de kaart mmc_read_sector(0); //Read Master Boot Record // In deze Master Boot record staan o.a. de partities vermeld. // We gaan er hier vanuit dat er slechts 1 partitie is aangemaakt. Daarbij is een groep van 4 bytes voor ons interessant. // Namelijk de Volume boot record adres, dat het begin van onze records aangeeft. // 4 First sector position relative to beginning of device Number of First Sector (Linear Address) // Als de eerste 3 data's bestaan uuit de codes EB,XX,90 dan hebben we te maken met geen partitie indeling. // Volume boot address is dan 0 , anders staat het volume boot adress op adress 0x1C6 if ((MMCBuffer[510]!=0x55)||(MMCBuffer[511]!=0xAA)) return(3); // Invalid boot sector if ((MMCBuffer[0]==0xEB)&&(MMCBuffer[2]==0x90)) // Detectie partitie indeling? DiskInfo.BootRecordAdress = 0; //Volume_Boot_Record_Address=0 else DiskInfo.BootRecordAdress = MMCBuffer[VBR_Addr]; // Volume_Boot_Record_Address waarde op adress 0x1C6 // Lees het boot record. mmc_read_sector (DiskInfo.BootRecordAdress); if ((MMCBuffer[510]!=0x55)||(MMCBuffer[511]!=0xAA)) return(4); // Invalid root sector bootp=(struct BootSec *)MMCBuffer; // De cluster size. (aantal sectors per cluster) staat in de BPB_secperclus DiskInfo.ClusterSize = bootp->BPB_SecPerClus; // Bereken het begin adres van de FAT (File alloc table) // gereserveerde sectors 2byte Het aantal sectoren vóórdat de eerste FAT volgt. // Dat is meestal 1 (de bootsector). DiskInfo.FATOffset = bootp->BPB_RsvdSecCnt + DiskInfo.BootRecordAdress; //Eerste Root sector = FAT offset + (aantal FAT's x aantal sectoren per FAT) DiskInfo.AantalFATsector = bootp->BPB_NumFATs * bootp->BPB_FATSz16; DiskInfo.RootRecord = DiskInfo.FATOffset + DiskInfo.AantalFATsector; DiskInfo.RootOffset = 0; // Standaard is het aantal bytes per sector 512 (bootp->BPB_BytesPerSec). // Een root entrie is standaard 32 bytes. // Het aantal rootentries is standaard 512 (BPB_RootEntCnt) // De data begint dan op record DiskInfo.FirstDataSector = (512 x 32) / 512 // DiskInfo.FirstDataSector geeft het begin record aan van de Data. dat meestal 32 sectors = 1 cluster boven de Rootrecord ligt. DiskInfo.FirstDataSector = DiskInfo.RootRecord + ((bootp->BPB_RootEntCnt * 32)/bootp->BPB_BytesPerSec); return(0); } // ############################################################################### //; Lezen van het commando register. Het MSB bit is de status van de busy flag. Is deze //; 1 dan is het LCD display bezig. bit0 t/m bit6 geeft het adres weer van de cursor plaats. //; Register B bevat de gelezen waarde char LCD_test_BF (void) { char result=0x80; //LCD_Getloc: // Hoogste 4 bits worden ingang, 3 laagste blijven uitgang DDRC=0x07; CNTR_RW=1; delay_ms(1); while (result>0x7F) { CNTR_ENABLE=1; // sbi PORTD,ENABLE ; Enable lijn hoog delay_ms(1); // rcall LCD_wait result=(PINC&0xF0); CNTR_ENABLE=0; // cbi PORTD,ENABLE ; Enable lijn laag delay_ms(1); // rcall LCD_wait CNTR_ENABLE=1; // sbi PORTD,ENABLE ; Enable lijn hoog delay_ms(1); // rcall LCD_wait result+=(PINC>>4); CNTR_ENABLE=0; // cbi PORTD,ENABLE ; Enable lijn laag } // alle 4 hoogste + 3 laagste bits worden uitgang DDRC=0xF7; //out DDRC,r20 CNTR_RW=0; // CNTR_RW=0; //cbi PORTD,RW ; R/W bit gereset in write mode return result; } void LCD_enable (void) { delay_us(10); CNTR_ENABLE=1; // ; Enable lijn wordt hoog delay_us(10); CNTR_ENABLE=0; // ; Enable lijn wordt laag delay_us(10); } void LCD_put(char writebyte) { char static poort; LCD_test_BF(); // ; Test of LCD klaar is poort=writebyte&0xF0; poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen //poort|=0x08; // PortD.3 reset moet hoog blijven PORTC=poort; CNTR_RS = 1; //sbi portC,4 ; RS bit geset LCD_enable(); poort=(writebyte<<4); poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen //poort|=0x08; // PortD.3 reset moet hoog blijven PORTC=poort; CNTR_RS = 1; //sbi portC,4 ; RS bit geset LCD_enable(); CNTR_RS = 0; //cbi portC,4 ; RS bit gereset } //;_________________________________________________________________ //; //; LCD_zend_text zend een text string naar het LCD display. en eindigen met karrakter 0 //; void LCD_zend_text(char *text) { char cnt=0; while (text[cnt]) { LCD_put(text[cnt]); cnt++; } } void LCD_commando (char LCDcmd) { char poort; LCD_test_BF(); //rcall LCD_test_BF ; Test of LCD klaar is poort=LCDcmd&0xF0; poort|=0x03; // Toetsenmatrix in stand vrij PORTC = poort; LCD_enable(); poort=LCDcmd<<4; poort|=0x03; // Toetsenmatrix in stand vrij PORTC = poort; LCD_enable(); } char Gettoets (void) { signed char toets=0,cnt=0xFF; // ldi r18,0x08 // Gettoets2: // Toetsenmatrix sturing DDRC=0x07; // de 3 laagste bits van poort C worden uitgang while ((cnt<8) && (toets==0)) { cnt++; PORTC=(cnt|0xF8); delay_ms(10); //rcall pauze1 ; Korte pauze. toets=(PINC&0x78)>>2; toets^=0x1E; } if (!toets) return 0; cnt&=0x07; // andi r18,0x07 if (cnt<4) // ; alle toetsen met r18 <4 zijn functie toetsen { cnt--; toets+=cnt; } else { // ; toetsen met waarde 2 = toets 0 t/m 3, 4 = tts4 to 7, 8= tts8 to B, 10 = tts C t/m F cnt&=0x03; // andi r18,0x03 if (toets==0x10) toets=0x0C; if (toets==0x02) toets=0x00; toets=(toets+cnt)|0x80; } //toets_end: // M.b.v. R18=3 word de toetsen matrix in een stand gezet, dat geen toets // kan worden ingedrukt met nadelige gevolgen. PORTC=0x03; return toets; } //; Gettoets levert een toets waarde. //; toetsen 0 t/m F dezelfde waarde met MSB bit=1 80 t/m 8F //; toetsen A->D =0x11 SV-0x10 RUN-0x09 LD-0x08 ME- 0x05 CPU-0x04 ME+ -0x03 SP-0x02 char GET_toets (void) { char result=0,result2=0; while ((result!=result2)||(result2==0)) // wacht totdat er een toets is ingedrukt { result2=Gettoets(); // delay_ms(100); result=Gettoets(); } // printf("#1 %u %u\n\r",result,result2); while (result2) result2=Gettoets(); // wacht totdat er een toets is losgelaten // printf("#2 %u %u\n\r",result,result2); return result; } unsigned int DirEntry(unsigned int Rootsector, unsigned int entrie) { struct DirEntry *dir; //pointer naar de ingang unsigned long sector; LED_GROEN_F1=1; LED_GEEL_F2=0; LED_ROOD_F3=1; sector= DiskInfo.RootRecord ; sector= sector + Rootsector + DiskInfo.RootOffset; mmc_read_sector (sector); // for (entrie=0;entrieDIR_Name[0] != 0) //verder geen files meer gevonden { // Als Attribuut <> 0x0F en de eerste karakter van de naam <> 0xE5 (delete file) if ((dir->DIR_Attr!=0x0F)&&(dir->DIR_Name[0]!=0xE5)) { if ( (dir->DIR_Name[8]=='H')&&(dir->DIR_Name[9]=='E')&&(dir->DIR_Name[10]=='X') ) // filter alleen op .HEX files { SectorPointer=((dir->DIR_FstClusLO-2) * DiskInfo.ClusterSize)+ DiskInfo.FirstDataSector; MMCfile.SectorPointer=0; //Wijst naar de in de buffer geladen sector in de cluster, dus niet de absolute sector MMCfile.DataPointer=0; //Wijst naar de byte in de buffer MMCfile.cluster=dir->DIR_FstClusLO; //Geeft het volgende cluster aan volgens de FAT MMCfile.ByteCnt=0; //wijst naar byte nummer in de file MMCfile.EndOfFile=0; MMCfile.File_Size=dir->DIR_FileSize; LCD_regel3; dir->DIR_Attr=0; LCD_zend_text(dir->DIR_Name); LED_GROEN_F1=0; LED_GEEL_F2=1; LED_ROOD_F3=1; return 0; } else return 1; }else return 1; } else { LCDRootsectorCnt=32; // Einde niet meer files LCDRootsectorCnt wordt op 32 gezet. return 2; } } // FindNextCluster zoekt vanuit een opgegeven cluster entry in de FAT naar een volgend entry // Input geeft het huidige cluster verwijzing op, is deze 0 dan wordt een geheel nieuw cluster verwijzing geretourneerd. // In het geval er een file geopend is in de read mode, volgt een volgend cluster verwijzing, in het geval de verwijzing 0xFFFF is volgt 0 als // een fout melding. // In het geval er een file geopend is in de write mode volgt een volgend of bij 0xFFFF een nieuw cluster. unsigned int FindNextCluster (unsigned char cluster) { unsigned int sector,NewCluster,clustersector; if (cluster>1) // Cluster verwijzer moet 2 of groter zijn en mag niet kleiner zijn! { clustersector=cluster/256; sector=DiskInfo.FATOffset+clustersector; mmc_read_sector (sector); NewCluster=MMCBuffer[cluster*2]+(MMCBuffer[(cluster*2)+1]<<8); } else NewCluster=0xFFFF; return NewCluster; } char fgetchar (void) { unsigned char MMCByte; unsigned long sector; MMCByte=MMCBuffer[MMCfile.DataPointer]; MMCfile.DataPointer++; MMCfile.ByteCnt++; if (MMCfile.ByteCnt > MMCfile.File_Size) { MMCfile.ByteCnt--; MMCfile.EndOfFile=1; return 0; } if (MMCfile.DataPointer >= 512) { MMCfile.SectorPointer++; if (MMCfile.SectorPointer >= DiskInfo.ClusterSize) // test clustersize { // printf("oud cluster: %lu\t %u\t",MMCfile.ByteCnt,MMCfile.cluster); MMCfile.cluster=FindNextCluster(MMCfile.cluster); // printf("new cluster: %u\n\r",MMCfile.cluster); MMCfile.SectorPointer=0; } sector= MMCfile.cluster-2; sector*=DiskInfo.ClusterSize; sector+=DiskInfo.FirstDataSector; sector+=MMCfile.SectorPointer; mmc_read_sector (sector); MMCfile.DataPointer=0; } return MMCByte; } unsigned int atoh(char *omzet) { unsigned int result=0; char *waarde,cnt; waarde=omzet; for (cnt=0;cnt<4;cnt++) { if ((waarde[cnt]>0x2F) && (waarde[cnt]<0x3A)) waarde[cnt]-= 0x30; if ((waarde[cnt]>0x40) && (waarde[cnt]<0x47)) waarde[cnt]-= 0x37; if (cnt==0) result+=waarde[cnt]*4096; if (cnt==1) result+=waarde[cnt]*256; if (cnt==2) result+=waarde[cnt]*16; if (cnt==3) result+=waarde[cnt]; // printf(" %02X %d\t",waarde[cnt],result); } return result; } void main(void) { // Declare your local variables here unsigned char result,cnt; unsigned long sector; // Port B initialization // PB0 out F1 in T0 user LED groen // PB1 out F2 LED geel // PB2 out F3 LED rood // PB3 out CS ethernet module // PB4 out SS = CS SD card // PB5 out MOSI // PB6 in MISO // PB7 out SCK PORTB=0xFB; DDRB=0xBF; // Port C initialization // PC0 out Keyboard colom 0 // PC1 out Keyboard colom 1 // PC2 out Keyboard colom 2 // PC3 in Keyboard row 0 // PC4 in/out Keyboard row 1 LCD display D4 // PC5 in/out Keyboard row 2 LCD display D5 // PC6 in/out Keyboard row 3 LCD display D6 // PC7 in/out LCD display D7 PORTC=0xFF; DDRC=0xF3; // Port D initialization // PD0 in RXD // PD1 out TXD // PD2 in INT0/SA user // PD3 in INT1/SB user // PD4 out LCD display Enable // PD5 out OC1A user // PD6 out LCD display R/W // PD7 out LCD display RS PORTD=0x20; DDRD=0xF0; /* SPCR = SPI commando register 7 6 5 4 3 2 1 0 SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0 SPIE = SPI interrupt enable SPE = SPI enable DORD = DATA order LSB of MSB eerst verzenden. normaal 0 MSTR = SPI MASter mode (1) SPI slave mode (0) CPOL = Clock polarity CPHA = clock phase SPR1/SPR0 = clock rate */ SPCR = 0x50; //zet als SPI-enable/Mastermode / prescaler SPR1+SPR0 = 00 SPSR = 0x00; //dubbele kloksnelheid BLBset(); // Set BLB bits LED_GROEN_F1=1; LED_GEEL_F2=1; LED_ROOD_F3=0; delay_ms(1000); //; LCD display sturing PORTC=0x30; //ldi A,0x30 ; DB4 + DB5 =1 8 bits mode // Schrijf 3x 0x30 naar het commando register. Dit om het LCD display te installeren // Het is belangrijk dat dit gebeurt na het resetten for (cnt=0;cnt<3;cnt++) { LCD_enable(); delay_ms (25); } LCD_test_BF(); // Test busy flag LCD display //; Zet het LCD display in 4 bits mode //ldi A,0x20 ; DB4 + =1 4 bits mode RS =0 R/W=0 Enable=0 PORTC=0x20; // out PORTC,A LCD_enable(); //rcall LCD_enable LCD_test_BF(); //rcall LCD_test_BF //ldi A,0x28 ; DB5 =1 DB4=0 4bits mode N=1 2 lines F= don't care LCD_commando(0x28); // Auto increment / freeze display LCD_commando(0x06); // disply on / cursor off / cursor pos. blinks off LCD_commando(0x0C); Clear_LCD; //strcpyf(LCDText,"bootloader"); LCD_zend_text(strBootloader); result=mmc_init(); LCD_regel2; if (result==0) { LCD_zend_text(strSDcardOK); } else { LCD_zend_text(strSDcardERROR); while (1) {}; } LCDentrieCnt=0; LCDRootsectorCnt=0; while (LCDRootsectorCnt<32) { LCDentrieCnt += 32; if (LCDentrieCnt>=BlockSize) { LCDentrieCnt = 0; LCDRootsectorCnt++; } //result=LCD_dir(); result=DirEntry(LCDRootsectorCnt,LCDentrieCnt); if (result==0) break; } LED_GROEN_F1=0; LED_GEEL_F2=1; LED_ROOD_F3=1; while (1) { // Place your code here // result=Gettoets(); // if (result) // { result=GET_toets(); // Haal de volgende toets op if (result==0x05) // toets ME- { while (LCDRootsectorCnt>=0) { LCDentrieCnt -= 32; if (LCDentrieCnt<0) { LCDentrieCnt = BlockSize; LCDRootsectorCnt--; } //result=LCD_dir(); result=DirEntry(LCDRootsectorCnt,LCDentrieCnt); if (result==0) break; } } else if (result==0x03) // toets ME+ { while (LCDRootsectorCnt<32) { LCDentrieCnt += 32; if (LCDentrieCnt>=BlockSize) { LCDentrieCnt = 0; LCDRootsectorCnt++; } //result=LCD_dir(); result=DirEntry(LCDRootsectorCnt,LCDentrieCnt); if (result==0) break; } } else if (result==0x09) // toets RUN { sector= MMCfile.cluster-2; sector*=DiskInfo.ClusterSize; sector+=DiskInfo.FirstDataSector; mmc_read_sector (sector); // Lees het eerste sector van de cluster FlashProgram(); delay_ms(5000); #asm("jmp 0x0000"); // forced reset } // } } } void FlashProgram(void) { char Byte8,cnt; static unsigned int word16,WRTadres,PRGadres,AantalBytes,Type,Checksum,Checksum2; char omzet[5],Data[17]; // //; Bootloader met het Intel intellec 8/MDS format // //; :bbaaaarr00112233445566778899AABBCCDDEEFFcc // //; bb= aantal bytes //; aaaa= adres //; rr = data type (normaal altijd 00, behalve bij het laatste record = 01 end of file)) //; 00 t/m FF = databytes //; cc = checksum // // //; Het laatste record is als volgt :000000001FF // //; r18 = checksum teller //; r20 = byte teller // LED_GROEN_F1=1; LED_GEEL_F2=1; LED_ROOD_F3=0; PRGadres=0xFFFF; while (MMCfile.EndOfFile==0) { Byte8=0; while ((MMCfile.EndOfFile==0)&&(Byte8!=':')) Byte8=fgetchar(); if (MMCfile.EndOfFile==0) { for (cnt=0;cnt<5;cnt++) omzet[cnt]=0; omzet[2]=fgetchar(); omzet[3]=fgetchar(); AantalBytes=atoh(omzet); Checksum2=AantalBytes; } else break; // printf("Bytes %u\t",AantalBytes); if (MMCfile.EndOfFile==0) { omzet[0]=fgetchar(); omzet[1]=fgetchar(); omzet[2]=fgetchar(); omzet[3]=fgetchar(); omzet[4]=0; LCD_regel4; LCD_zend_text(omzet); WRTadres=atoh(omzet); Checksum2+=(WRTadres&0xFF); Checksum2+=(WRTadres>>8); } // printf("%04X %u\t",WRTadres,AantalBytes); if (MMCfile.EndOfFile==0) { for (cnt=0;cnt<5;cnt++) omzet[cnt]=0; omzet[2]=fgetchar(); omzet[3]=fgetchar(); Type=atoh(omzet); Checksum2+=Type; } // printf("Type %u\t",Type); for (cnt=0;cnt>8);// write PRGadres blok geldt alleen niet voor PRGadres=0xFFFF else if (Type==0x02) {} // Geen data verwerking. else { for (cnt=0;cnt>8);// write PRGadres blok geldt alleen niet voor PRGadres=0xFFFF WRITE_PAGE(PRGadres); } // printf("erase adres blok %02X\n\r",(WRTadres&0xFF00)>>8); // erase WRTadres blok ERASE_PAGE(WRTadres); PRGadres=WRTadres; } DO_SPM(word16,WRTadres); WRTadres+=2; } } } // else printf("Checksum not OK %02X %02X ",Checksum,Checksum2); } LED_GROEN_F1=0; LED_GEEL_F2=1; LED_ROOD_F3=1; } // //; Bij het programmeren wordt voortdurend gekeken of de page van 32 of 64 bytes niet wordt //; overschreden. Is dit wel het geval dan moet eerst de page naar de flash geschreven worden. //; voor dat er verder wordt gegaan. //; X reg bevat de vorige Z waarde(adres) en wordt vergeleken met de nieuwe Z waarde (adres) //; Als het 7e bit (bij 64 bits pages) veranderd, geeft dit de een page verandering aan. // //;Device Flash Size Page Size PCWORD No.of Pages PCPAGE PCMSB //;ATmega48 2K words(4K bytes) 32 words PC[4:0] 64 PC[10:5] 10 //;ATmega88 4K words(8K bytes) 32 words PC[4:0] 128 PC[11:5] 11 //;ATmega168 8K words(16K bytes) 64 words PC[5:0] 128 PC[12:6] 12 //;ATmega128 64K words(128K bytes) 128 words PC[6:0] 512 PC[15:7] 15 //;ATmega644 32K words(64K bytes) 128 words PC[6:0] 256 PC[14:7] 14 //;ATmega32 16K words(32K bytes) 64 words PC[5:0] 256 PC[13:6] 13 //;ATmega8515 4K words(8K bytes) 32 words PC[4:0] 128 PC[11:5] 11 // // // // //; ########################################################################### // //; het programma wordt geprogrammeerd op de laatste gedeelte van het flash geheugen. //; Het mag niet onder het adres 1C00 komen !!! // //; SPMSCR register 0068 //; SPMIE RWWSB - RWWSRE BLBSET PGWRT PGERS SPMEM // // // void DO_SPM(int data, int adres) { // DO_SPM zend data naar de zelf programmer. // mode=1 = Data wordt in het tijdelijke geheugen geschreven. #asm push r16 push r17 LD R30,Y ; adress low naar ZL LDD R31,Y+1 ; adress high naar ZH LDD r0,Y+2 ; data low gekopieerd naar r0 LDD r1,Y+3 ; data high gekopieerd naar r1 ldi r17,0x01 call Do_spm pop r17 pop r16 #endasm } void ERASE_PAGE(int adres) { #asm LD R30,Y ; adress low naar ZL LDD R31,Y+1 ; adress high naar ZH push r16 push r17 //call Erase_page ldi r17,0x03 call Do_spm ; erase page call test_RWW pop r17 pop r16 #endasm } void WRITE_PAGE(int adres) { #asm LD R30,Y ; adress low naar ZL LDD R31,Y+1 ; adress high naar ZH push r16 push r17 //call Write_page ldi r17,0x05 call Do_spm ; write page call test_RWW pop r17 pop r16 #endasm } void BLBset(void) { #asm push r16 push r17 ldi r16,0xEF mov r0,R16 ; R0 bevat de data van de BLBset byte Alleen BLB11=0 om data schrijven in de BLS (boot loader selection) te verhinderem ldi r17,0x09 call Do_spm ; set BLB call test_RWW pop r17 pop r16 #endasm } #asm Do_spm: spm_test_spen: in r16,SPMCSR sbrc r16,0 ; test SPMEN bit of 0 jmp spm_test_spen out SPMCSR,r17 spm ret test_RWW: in r16,SPMCSR sbrs r16,6 ret ldi r17,0x11 rcall Do_spm rjmp test_RWW //Write_page: //ldi r17,0x05 //call Do_spm ; write page //call test_RWW //ret //Erase_page: //ldi r17,0x03 //call Do_spm ; erase page //call test_RWW //ret #endasm