Chester Hamilton
/
AVR_SPI_Programmer_v2
Revision 0:52ce2a69824f, committed 2010-06-21
- Comitter:
- Chamilton09
- Date:
- Mon Jun 21 14:43:29 2010 +0000
- Commit message:
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
mbed.bld | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 52ce2a69824f main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Jun 21 14:43:29 2010 +0000 @@ -0,0 +1,261 @@ +// Code to implement ICSP of an AVR using the ISP on the mBed pins 5,6,7 +// and 8 as RESET + +//NOTES: -load hex file onto the mBed as a file named "avr" +// -Change TARGET_CLK to a suiteable value for your particular avr (it gets divided by 2 for ATMega88) +// -Change the max page size to suite the microcontroller (change the 64 only) + +#include "mbed.h" +#define LSB(I) ((I) & 0xFF) +#define MSB(I) (((I) & 0xF00) >> 8) + +#define TARGET_CLK 1000000L +#define MAX_PAGE_SIZE (64 >> 1) //divide max page size by 2 to get number of words per page + +SPI spi(p5, p6, p7); // mosi, miso, sclk/ +DigitalOut reset(p8); //RESET + +Serial pc(USBTX, USBRX); // tx, rx + +LocalFileSystem local("local"); + + +int enable_prog_mode() //function to enable prog mode +{ + int failed = 0; + + while(failed < 5) //loop to try to enable programming mode 5 times + { + spi.write(0xAC); + spi.write(0x53); + int prog_en_check = spi.write(0x00); + if(prog_en_check == 0x53) { //if data read on 3rd byte load is 0x53 + spi.write(0x00); //programming mode was enabled...good job! + pc.printf("\nProgramming mode enabled...\n"); + return 0; + } + else{ + pc.printf("Programming mode failed!\n"); + pc.printf("%d\n",prog_en_check); + failed++; + reset = 1; //pulse reset and try again + reset = 0; + pc.printf("Trying again...\n"); + wait(0.5); + } + } + return -1; //Bummer... +} + +//A function to poll BSY to prevent loading a new instruction prematurely +void still_programming() +{ + int check = 1; + while(check == 1) + { + spi.write(0xF0); + spi.write(0x00); + spi.write(0x00); + check = spi.write(0x00); //read data byte out + } +} + +//A function to send the chip erase command +void chip_erase() +{ + pc.printf("Chip erase initiated...\n"); + spi.write(0xAC); + spi.write(0x80); + spi.write(0x00); + spi.write(0x00); + still_programming(); + pc.printf("Chip erase completed!\n"); + reset = 1; + wait(0.020); + reset = 0; + wait(0.020); + enable_prog_mode(); +} + + +void write_prog_page(uint16_t addr) +{ + //write program memory page + spi.write(0x4C); + spi.write(MSB(addr)); + spi.write(LSB(addr)); + spi.write(0x00); + still_programming(); //make sure the operation worked + // pc.printf("Wrote a flash page.\n"); +} + + +//function to load and write program memory +//args: addr is the 12 bit address of the memory location +// low_data and high_data are the values to write to that location +void load_prog_page(uint16_t addr, uint8_t low_data, uint8_t high_data)//int addr_MSB, +{ + //load program memory low byte (little endian) + spi.write(0x40); + spi.write(0x00); + spi.write(LSB(addr)); + spi.write(low_data); + + //load program memory high byte + spi.write(0x48); + spi.write(0x00); + spi.write(LSB(addr)); + spi.write(high_data); + //pc.printf(" Wrote: %x %x to LSB address: %x\n", high_data, low_data, LSB(addr)); + + // write page if 32 words have now been written + if(addr % MAX_PAGE_SIZE == (MAX_PAGE_SIZE-1)) + write_prog_page(addr); +} + +void write_lock_bits(uint8_t bits) +{ + bits = bits & 0xFF; + spi.write(0xAC); + spi.write(0xE0); + spi.write(0x00); + spi.write(bits); + still_programming(); + pc.printf("Wrote lock bits...\n"); +} + +void write_fuse_bits(uint8_t bits) +{ + bits = bits & 0xFF; + spi.write(0xAC); + spi.write(0xA0); + spi.write(0x00); + spi.write(bits); + still_programming(); + pc.printf("Wrote fuse bits...\n"); +} + +void write_fuse_bits_high(uint8_t bits) +{ + bits = bits & 0xFF; + spi.write(0xAC); + spi.write(0xA8); + spi.write(0x00); + spi.write(bits); + still_programming(); + pc.printf("Wrote fuse bits high...\n"); +} + +void write_extended_fuse_bits(uint8_t bits) +{ + bits = bits & 0xFF; + spi.write(0xAC); + spi.write(0xA4); + spi.write(0x00); + spi.write(bits); + still_programming(); + pc.printf("Wrote extended fuse bits...\n"); +} + +uint8_t read_byte(FILE *file) +{ + char ascii_char[2]; + fread(&ascii_char, 1, 2, file); + return (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4) + | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55)); +} + +void read_prog_flash(uint8_t addr_MSB, uint8_t addr_LSB) +{ + spi.write(0x28); + spi.write(addr_MSB); + spi.write(addr_LSB); + pc.printf("At address LSB %x: MSB: %x - %x ",addr_LSB,addr_MSB,spi.write(0x00)); + spi.write(0x20); + spi.write(addr_MSB); + spi.write(addr_LSB); + pc.printf("%x\n",spi.write(0x00)); +} + +int main() { + reset = 1; + // Setup the spi for 8 bit data,writing data on the rising SCK edge, + // and reading data on the falling SCK edge as according to AVR specs + // with a 1MHz clock rate + pc.printf("\nPress any button to program the AVR.\n"); + char c = pc.getc(); + + spi.format(8,1); //SPI format: write data on rising edge, read on falling + //w/ a base clock value of zero + spi.frequency(TARGET_CLK >> 2); + //wait(0.5); + pc.printf("SPI interface started...\n"); + + // Select the device by seting chip select low + reset = 0; + wait(0.02); + + if(enable_prog_mode() != 0) //Enable programming mode and check for errors + return -1; + spi.write(0x30); + spi.write(0x00); + spi.write(0x00); + pc.printf("SIGNATURE BYTE: %x\n",spi.write(0x00)); + chip_erase(); + + write_lock_bits(0xFF); //1111 1111 + write_fuse_bits(0x62); //1110 0010 + write_fuse_bits_high(0xDF); //1101 1111 + write_extended_fuse_bits(0xF9); //1111 1001 + + //Opening a file on local FS as in example code + pc.printf("Opening File...\n"); + int flag = 0; + FILE *hex_file; + hex_file = fopen("/local/avr","r"); + if(hex_file !=NULL) + { + uint16_t address = 0; + char temp; + temp = fgetc(hex_file); + while(flag == 0) + { + if(temp == ':') + { + uint8_t length = read_byte(hex_file); + if(length == 0){ + flag = 1; + printf("EOF line reached.\n"); + } + else{ + fseek(hex_file, 6, SEEK_CUR); //2 if reading address + + for(uint8_t i=0;i<length;i+=2){ + uint8_t low_data = read_byte(hex_file); + uint8_t high_data = read_byte(hex_file); + + //load data bytes here + load_prog_page(address, low_data, high_data); + + address++; + } + while((temp = fgetc(hex_file)) != ':'); + //pc.printf("\n"); + } + } + else flag =1; + } + pc.printf("WRITE THE PAGE!\n");//write page here + write_prog_page(address); + fclose(hex_file); + } + else { + pc.printf("Failed to open the file...check the name.\n"); + } + pc.printf("Successfully programmed!(hopefully...)\n"); + + // Deselect the device + reset = 1; + wait(0.02); + return 0; +} \ No newline at end of file
diff -r 000000000000 -r 52ce2a69824f mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Jun 21 14:43:29 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/029aa53d7323