Chester Hamilton / Mbed 2 deprecated AVR_SPI_Programmer_v2

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // Code to implement ICSP of an AVR using the ISP on the mBed pins 5,6,7 
00002 // and 8 as RESET
00003 
00004 //NOTES:    -load hex file onto the mBed as a file named "avr"
00005 //          -Change TARGET_CLK to a suiteable value for your particular avr (it gets divided by 2 for ATMega88)
00006 //          -Change the max page size to suite the microcontroller (change the 64 only)
00007 
00008 #include "mbed.h"
00009 #define LSB(I) ((I) & 0xFF)
00010 #define MSB(I) (((I) & 0xF00) >> 8)
00011 
00012 #define TARGET_CLK 1000000L
00013 #define MAX_PAGE_SIZE (64 >> 1) //divide max page size by 2 to get number of words per page                                    
00014                                                    
00015 SPI spi(p5, p6, p7); // mosi, miso, sclk/
00016 DigitalOut reset(p8);   //RESET
00017 
00018 Serial pc(USBTX, USBRX); // tx, rx
00019 
00020 LocalFileSystem local("local");
00021 
00022 
00023 int enable_prog_mode() //function to enable prog mode
00024 {
00025     int failed = 0;
00026     
00027     while(failed < 5) //loop to try to enable programming mode 5 times
00028     {
00029         spi.write(0xAC);
00030         spi.write(0x53);
00031         int prog_en_check = spi.write(0x00);
00032         if(prog_en_check == 0x53) { //if data read on 3rd byte load is 0x53
00033             spi.write(0x00);        //programming mode was enabled...good job!
00034             pc.printf("\nProgramming mode enabled...\n");
00035             return 0;
00036         }      
00037         else{
00038             pc.printf("Programming mode failed!\n");
00039             pc.printf("%d\n",prog_en_check); 
00040             failed++;
00041             reset = 1; //pulse reset and try again
00042             reset = 0;
00043             pc.printf("Trying again...\n");
00044             wait(0.5);
00045         }
00046      }
00047     return -1; //Bummer...
00048 }
00049 
00050 //A function to poll BSY to prevent loading a new instruction prematurely
00051 void still_programming() 
00052 {
00053     int check = 1;
00054     while(check == 1)
00055     {
00056         spi.write(0xF0);
00057         spi.write(0x00);
00058         spi.write(0x00);
00059         check = spi.write(0x00); //read data byte out
00060     }
00061 }
00062 
00063 //A function to send the chip erase command
00064 void chip_erase() 
00065 {
00066         pc.printf("Chip erase initiated...\n");
00067         spi.write(0xAC);
00068         spi.write(0x80);
00069         spi.write(0x00);
00070         spi.write(0x00);
00071         still_programming();
00072         pc.printf("Chip erase completed!\n");
00073         reset = 1;
00074         wait(0.020);
00075         reset = 0;
00076         wait(0.020);
00077         enable_prog_mode();
00078 }
00079 
00080 
00081 void write_prog_page(uint16_t addr)
00082 {
00083     //write program memory page
00084     spi.write(0x4C);
00085     spi.write(MSB(addr));
00086     spi.write(LSB(addr));
00087     spi.write(0x00);
00088     still_programming(); //make sure the operation worked
00089    // pc.printf("Wrote a flash page.\n"); 
00090 }
00091 
00092 
00093 //function to load and write program memory
00094 //args: addr is the 12 bit address of the memory location
00095 //      low_data and high_data are the values to write to that location
00096 void load_prog_page(uint16_t addr, uint8_t low_data, uint8_t high_data)//int addr_MSB, 
00097 {
00098     //load program memory low byte (little endian)
00099     spi.write(0x40);
00100     spi.write(0x00);
00101     spi.write(LSB(addr));
00102     spi.write(low_data);
00103     
00104     //load program memory high byte
00105     spi.write(0x48);
00106     spi.write(0x00);
00107     spi.write(LSB(addr));
00108     spi.write(high_data);
00109     //pc.printf(" Wrote: %x %x to LSB address: %x\n", high_data, low_data, LSB(addr));
00110    
00111     // write page if 32 words have now been written
00112     if(addr % MAX_PAGE_SIZE == (MAX_PAGE_SIZE-1))
00113         write_prog_page(addr);
00114 }
00115 
00116 void write_lock_bits(uint8_t bits)
00117 {
00118     bits = bits & 0xFF;
00119     spi.write(0xAC);
00120     spi.write(0xE0);
00121     spi.write(0x00);
00122     spi.write(bits);
00123     still_programming();
00124     pc.printf("Wrote lock bits...\n");
00125 }
00126 
00127 void write_fuse_bits(uint8_t bits)
00128 {
00129     bits = bits & 0xFF;
00130     spi.write(0xAC);
00131     spi.write(0xA0);
00132     spi.write(0x00);
00133     spi.write(bits);
00134     still_programming();
00135     pc.printf("Wrote fuse bits...\n");
00136 }
00137 
00138 void write_fuse_bits_high(uint8_t bits)
00139 {
00140     bits = bits & 0xFF;
00141     spi.write(0xAC);
00142     spi.write(0xA8);
00143     spi.write(0x00);
00144     spi.write(bits);
00145     still_programming();
00146     pc.printf("Wrote fuse bits high...\n");
00147 }
00148 
00149 void write_extended_fuse_bits(uint8_t bits)
00150 {
00151     bits = bits & 0xFF;
00152     spi.write(0xAC);
00153     spi.write(0xA4);
00154     spi.write(0x00);
00155     spi.write(bits);
00156     still_programming();
00157     pc.printf("Wrote extended fuse bits...\n");
00158 }
00159 
00160 uint8_t read_byte(FILE *file)
00161 {
00162     char ascii_char[2];
00163     fread(&ascii_char, 1, 2, file);
00164     return   (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4)
00165             | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55));
00166 }
00167 
00168 void read_prog_flash(uint8_t addr_MSB, uint8_t addr_LSB)
00169 {
00170     spi.write(0x28);
00171     spi.write(addr_MSB);
00172     spi.write(addr_LSB);
00173     pc.printf("At address LSB %x: MSB: %x - %x ",addr_LSB,addr_MSB,spi.write(0x00));
00174     spi.write(0x20);
00175     spi.write(addr_MSB);
00176     spi.write(addr_LSB);
00177     pc.printf("%x\n",spi.write(0x00));      
00178 }
00179 
00180 int main() {
00181     reset = 1;
00182     // Setup the spi for 8 bit data,writing data on the rising SCK edge,
00183     // and reading data on the falling SCK edge as according to AVR specs
00184     // with a 1MHz clock rate
00185     pc.printf("\nPress any button to program the AVR.\n");
00186     char c = pc.getc();
00187     
00188     spi.format(8,1);        //SPI format: write data on rising edge, read on falling
00189                             //w/ a base clock value of zero
00190     spi.frequency(TARGET_CLK >> 2);
00191     //wait(0.5);
00192     pc.printf("SPI interface started...\n");
00193     
00194     // Select the device by seting chip select low
00195     reset = 0;
00196     wait(0.02); 
00197 
00198     if(enable_prog_mode() != 0)  //Enable programming mode and check for errors
00199         return -1;
00200     spi.write(0x30);
00201     spi.write(0x00);
00202     spi.write(0x00);
00203     pc.printf("SIGNATURE BYTE: %x\n",spi.write(0x00));
00204     chip_erase();
00205     
00206     write_lock_bits(0xFF);                  //1111 1111
00207     write_fuse_bits(0x62);                  //1110 0010
00208     write_fuse_bits_high(0xDF);             //1101 1111
00209     write_extended_fuse_bits(0xF9);         //1111 1001
00210     
00211     //Opening a file on local FS as in example code
00212     pc.printf("Opening File...\n"); 
00213     int flag = 0;
00214     FILE *hex_file;
00215     hex_file = fopen("/local/avr","r");
00216     if(hex_file !=NULL)
00217     {    
00218         uint16_t address = 0;
00219         char temp;
00220         temp = fgetc(hex_file);
00221         while(flag == 0)
00222         {
00223             if(temp == ':')
00224             {
00225                 uint8_t length = read_byte(hex_file);
00226                 if(length == 0){
00227                     flag = 1;
00228                     printf("EOF line reached.\n");
00229                 }
00230                 else{
00231                     fseek(hex_file, 6, SEEK_CUR); //2 if reading address
00232                     
00233                     for(uint8_t i=0;i<length;i+=2){
00234                         uint8_t low_data = read_byte(hex_file);
00235                         uint8_t high_data = read_byte(hex_file);
00236                        
00237                         //load data bytes here
00238                         load_prog_page(address, low_data, high_data);
00239                         
00240                         address++;
00241                     }
00242                     while((temp = fgetc(hex_file)) != ':');
00243                     //pc.printf("\n");             
00244                 }
00245             }
00246             else flag =1;
00247         }
00248         pc.printf("WRITE THE PAGE!\n");//write page here
00249         write_prog_page(address);
00250         fclose(hex_file);
00251     }
00252     else {
00253         pc.printf("Failed to open the file...check the name.\n");          
00254     }
00255     pc.printf("Successfully programmed!(hopefully...)\n");    
00256     
00257     // Deselect the device
00258     reset = 1;
00259     wait(0.02);
00260     return 0;    
00261 }