Code to program an AVR microcontroller over SPI using the mBed's first SPI port. The AVR must support ICSP. Alter max page size from 64 to the matching page size for your microcontroller. Alter the clock to the minimum clock speed for your microcontroller. Has only been tested with ATMega88.

Dependencies:   mbed

Committer:
Chamilton09
Date:
Mon Jun 21 14:43:29 2010 +0000
Revision:
0:52ce2a69824f

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Chamilton09 0:52ce2a69824f 1 // Code to implement ICSP of an AVR using the ISP on the mBed pins 5,6,7
Chamilton09 0:52ce2a69824f 2 // and 8 as RESET
Chamilton09 0:52ce2a69824f 3
Chamilton09 0:52ce2a69824f 4 //NOTES: -load hex file onto the mBed as a file named "avr"
Chamilton09 0:52ce2a69824f 5 // -Change TARGET_CLK to a suiteable value for your particular avr (it gets divided by 2 for ATMega88)
Chamilton09 0:52ce2a69824f 6 // -Change the max page size to suite the microcontroller (change the 64 only)
Chamilton09 0:52ce2a69824f 7
Chamilton09 0:52ce2a69824f 8 #include "mbed.h"
Chamilton09 0:52ce2a69824f 9 #define LSB(I) ((I) & 0xFF)
Chamilton09 0:52ce2a69824f 10 #define MSB(I) (((I) & 0xF00) >> 8)
Chamilton09 0:52ce2a69824f 11
Chamilton09 0:52ce2a69824f 12 #define TARGET_CLK 1000000L
Chamilton09 0:52ce2a69824f 13 #define MAX_PAGE_SIZE (64 >> 1) //divide max page size by 2 to get number of words per page
Chamilton09 0:52ce2a69824f 14
Chamilton09 0:52ce2a69824f 15 SPI spi(p5, p6, p7); // mosi, miso, sclk/
Chamilton09 0:52ce2a69824f 16 DigitalOut reset(p8); //RESET
Chamilton09 0:52ce2a69824f 17
Chamilton09 0:52ce2a69824f 18 Serial pc(USBTX, USBRX); // tx, rx
Chamilton09 0:52ce2a69824f 19
Chamilton09 0:52ce2a69824f 20 LocalFileSystem local("local");
Chamilton09 0:52ce2a69824f 21
Chamilton09 0:52ce2a69824f 22
Chamilton09 0:52ce2a69824f 23 int enable_prog_mode() //function to enable prog mode
Chamilton09 0:52ce2a69824f 24 {
Chamilton09 0:52ce2a69824f 25 int failed = 0;
Chamilton09 0:52ce2a69824f 26
Chamilton09 0:52ce2a69824f 27 while(failed < 5) //loop to try to enable programming mode 5 times
Chamilton09 0:52ce2a69824f 28 {
Chamilton09 0:52ce2a69824f 29 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 30 spi.write(0x53);
Chamilton09 0:52ce2a69824f 31 int prog_en_check = spi.write(0x00);
Chamilton09 0:52ce2a69824f 32 if(prog_en_check == 0x53) { //if data read on 3rd byte load is 0x53
Chamilton09 0:52ce2a69824f 33 spi.write(0x00); //programming mode was enabled...good job!
Chamilton09 0:52ce2a69824f 34 pc.printf("\nProgramming mode enabled...\n");
Chamilton09 0:52ce2a69824f 35 return 0;
Chamilton09 0:52ce2a69824f 36 }
Chamilton09 0:52ce2a69824f 37 else{
Chamilton09 0:52ce2a69824f 38 pc.printf("Programming mode failed!\n");
Chamilton09 0:52ce2a69824f 39 pc.printf("%d\n",prog_en_check);
Chamilton09 0:52ce2a69824f 40 failed++;
Chamilton09 0:52ce2a69824f 41 reset = 1; //pulse reset and try again
Chamilton09 0:52ce2a69824f 42 reset = 0;
Chamilton09 0:52ce2a69824f 43 pc.printf("Trying again...\n");
Chamilton09 0:52ce2a69824f 44 wait(0.5);
Chamilton09 0:52ce2a69824f 45 }
Chamilton09 0:52ce2a69824f 46 }
Chamilton09 0:52ce2a69824f 47 return -1; //Bummer...
Chamilton09 0:52ce2a69824f 48 }
Chamilton09 0:52ce2a69824f 49
Chamilton09 0:52ce2a69824f 50 //A function to poll BSY to prevent loading a new instruction prematurely
Chamilton09 0:52ce2a69824f 51 void still_programming()
Chamilton09 0:52ce2a69824f 52 {
Chamilton09 0:52ce2a69824f 53 int check = 1;
Chamilton09 0:52ce2a69824f 54 while(check == 1)
Chamilton09 0:52ce2a69824f 55 {
Chamilton09 0:52ce2a69824f 56 spi.write(0xF0);
Chamilton09 0:52ce2a69824f 57 spi.write(0x00);
Chamilton09 0:52ce2a69824f 58 spi.write(0x00);
Chamilton09 0:52ce2a69824f 59 check = spi.write(0x00); //read data byte out
Chamilton09 0:52ce2a69824f 60 }
Chamilton09 0:52ce2a69824f 61 }
Chamilton09 0:52ce2a69824f 62
Chamilton09 0:52ce2a69824f 63 //A function to send the chip erase command
Chamilton09 0:52ce2a69824f 64 void chip_erase()
Chamilton09 0:52ce2a69824f 65 {
Chamilton09 0:52ce2a69824f 66 pc.printf("Chip erase initiated...\n");
Chamilton09 0:52ce2a69824f 67 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 68 spi.write(0x80);
Chamilton09 0:52ce2a69824f 69 spi.write(0x00);
Chamilton09 0:52ce2a69824f 70 spi.write(0x00);
Chamilton09 0:52ce2a69824f 71 still_programming();
Chamilton09 0:52ce2a69824f 72 pc.printf("Chip erase completed!\n");
Chamilton09 0:52ce2a69824f 73 reset = 1;
Chamilton09 0:52ce2a69824f 74 wait(0.020);
Chamilton09 0:52ce2a69824f 75 reset = 0;
Chamilton09 0:52ce2a69824f 76 wait(0.020);
Chamilton09 0:52ce2a69824f 77 enable_prog_mode();
Chamilton09 0:52ce2a69824f 78 }
Chamilton09 0:52ce2a69824f 79
Chamilton09 0:52ce2a69824f 80
Chamilton09 0:52ce2a69824f 81 void write_prog_page(uint16_t addr)
Chamilton09 0:52ce2a69824f 82 {
Chamilton09 0:52ce2a69824f 83 //write program memory page
Chamilton09 0:52ce2a69824f 84 spi.write(0x4C);
Chamilton09 0:52ce2a69824f 85 spi.write(MSB(addr));
Chamilton09 0:52ce2a69824f 86 spi.write(LSB(addr));
Chamilton09 0:52ce2a69824f 87 spi.write(0x00);
Chamilton09 0:52ce2a69824f 88 still_programming(); //make sure the operation worked
Chamilton09 0:52ce2a69824f 89 // pc.printf("Wrote a flash page.\n");
Chamilton09 0:52ce2a69824f 90 }
Chamilton09 0:52ce2a69824f 91
Chamilton09 0:52ce2a69824f 92
Chamilton09 0:52ce2a69824f 93 //function to load and write program memory
Chamilton09 0:52ce2a69824f 94 //args: addr is the 12 bit address of the memory location
Chamilton09 0:52ce2a69824f 95 // low_data and high_data are the values to write to that location
Chamilton09 0:52ce2a69824f 96 void load_prog_page(uint16_t addr, uint8_t low_data, uint8_t high_data)//int addr_MSB,
Chamilton09 0:52ce2a69824f 97 {
Chamilton09 0:52ce2a69824f 98 //load program memory low byte (little endian)
Chamilton09 0:52ce2a69824f 99 spi.write(0x40);
Chamilton09 0:52ce2a69824f 100 spi.write(0x00);
Chamilton09 0:52ce2a69824f 101 spi.write(LSB(addr));
Chamilton09 0:52ce2a69824f 102 spi.write(low_data);
Chamilton09 0:52ce2a69824f 103
Chamilton09 0:52ce2a69824f 104 //load program memory high byte
Chamilton09 0:52ce2a69824f 105 spi.write(0x48);
Chamilton09 0:52ce2a69824f 106 spi.write(0x00);
Chamilton09 0:52ce2a69824f 107 spi.write(LSB(addr));
Chamilton09 0:52ce2a69824f 108 spi.write(high_data);
Chamilton09 0:52ce2a69824f 109 //pc.printf(" Wrote: %x %x to LSB address: %x\n", high_data, low_data, LSB(addr));
Chamilton09 0:52ce2a69824f 110
Chamilton09 0:52ce2a69824f 111 // write page if 32 words have now been written
Chamilton09 0:52ce2a69824f 112 if(addr % MAX_PAGE_SIZE == (MAX_PAGE_SIZE-1))
Chamilton09 0:52ce2a69824f 113 write_prog_page(addr);
Chamilton09 0:52ce2a69824f 114 }
Chamilton09 0:52ce2a69824f 115
Chamilton09 0:52ce2a69824f 116 void write_lock_bits(uint8_t bits)
Chamilton09 0:52ce2a69824f 117 {
Chamilton09 0:52ce2a69824f 118 bits = bits & 0xFF;
Chamilton09 0:52ce2a69824f 119 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 120 spi.write(0xE0);
Chamilton09 0:52ce2a69824f 121 spi.write(0x00);
Chamilton09 0:52ce2a69824f 122 spi.write(bits);
Chamilton09 0:52ce2a69824f 123 still_programming();
Chamilton09 0:52ce2a69824f 124 pc.printf("Wrote lock bits...\n");
Chamilton09 0:52ce2a69824f 125 }
Chamilton09 0:52ce2a69824f 126
Chamilton09 0:52ce2a69824f 127 void write_fuse_bits(uint8_t bits)
Chamilton09 0:52ce2a69824f 128 {
Chamilton09 0:52ce2a69824f 129 bits = bits & 0xFF;
Chamilton09 0:52ce2a69824f 130 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 131 spi.write(0xA0);
Chamilton09 0:52ce2a69824f 132 spi.write(0x00);
Chamilton09 0:52ce2a69824f 133 spi.write(bits);
Chamilton09 0:52ce2a69824f 134 still_programming();
Chamilton09 0:52ce2a69824f 135 pc.printf("Wrote fuse bits...\n");
Chamilton09 0:52ce2a69824f 136 }
Chamilton09 0:52ce2a69824f 137
Chamilton09 0:52ce2a69824f 138 void write_fuse_bits_high(uint8_t bits)
Chamilton09 0:52ce2a69824f 139 {
Chamilton09 0:52ce2a69824f 140 bits = bits & 0xFF;
Chamilton09 0:52ce2a69824f 141 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 142 spi.write(0xA8);
Chamilton09 0:52ce2a69824f 143 spi.write(0x00);
Chamilton09 0:52ce2a69824f 144 spi.write(bits);
Chamilton09 0:52ce2a69824f 145 still_programming();
Chamilton09 0:52ce2a69824f 146 pc.printf("Wrote fuse bits high...\n");
Chamilton09 0:52ce2a69824f 147 }
Chamilton09 0:52ce2a69824f 148
Chamilton09 0:52ce2a69824f 149 void write_extended_fuse_bits(uint8_t bits)
Chamilton09 0:52ce2a69824f 150 {
Chamilton09 0:52ce2a69824f 151 bits = bits & 0xFF;
Chamilton09 0:52ce2a69824f 152 spi.write(0xAC);
Chamilton09 0:52ce2a69824f 153 spi.write(0xA4);
Chamilton09 0:52ce2a69824f 154 spi.write(0x00);
Chamilton09 0:52ce2a69824f 155 spi.write(bits);
Chamilton09 0:52ce2a69824f 156 still_programming();
Chamilton09 0:52ce2a69824f 157 pc.printf("Wrote extended fuse bits...\n");
Chamilton09 0:52ce2a69824f 158 }
Chamilton09 0:52ce2a69824f 159
Chamilton09 0:52ce2a69824f 160 uint8_t read_byte(FILE *file)
Chamilton09 0:52ce2a69824f 161 {
Chamilton09 0:52ce2a69824f 162 char ascii_char[2];
Chamilton09 0:52ce2a69824f 163 fread(&ascii_char, 1, 2, file);
Chamilton09 0:52ce2a69824f 164 return (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4)
Chamilton09 0:52ce2a69824f 165 | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55));
Chamilton09 0:52ce2a69824f 166 }
Chamilton09 0:52ce2a69824f 167
Chamilton09 0:52ce2a69824f 168 void read_prog_flash(uint8_t addr_MSB, uint8_t addr_LSB)
Chamilton09 0:52ce2a69824f 169 {
Chamilton09 0:52ce2a69824f 170 spi.write(0x28);
Chamilton09 0:52ce2a69824f 171 spi.write(addr_MSB);
Chamilton09 0:52ce2a69824f 172 spi.write(addr_LSB);
Chamilton09 0:52ce2a69824f 173 pc.printf("At address LSB %x: MSB: %x - %x ",addr_LSB,addr_MSB,spi.write(0x00));
Chamilton09 0:52ce2a69824f 174 spi.write(0x20);
Chamilton09 0:52ce2a69824f 175 spi.write(addr_MSB);
Chamilton09 0:52ce2a69824f 176 spi.write(addr_LSB);
Chamilton09 0:52ce2a69824f 177 pc.printf("%x\n",spi.write(0x00));
Chamilton09 0:52ce2a69824f 178 }
Chamilton09 0:52ce2a69824f 179
Chamilton09 0:52ce2a69824f 180 int main() {
Chamilton09 0:52ce2a69824f 181 reset = 1;
Chamilton09 0:52ce2a69824f 182 // Setup the spi for 8 bit data,writing data on the rising SCK edge,
Chamilton09 0:52ce2a69824f 183 // and reading data on the falling SCK edge as according to AVR specs
Chamilton09 0:52ce2a69824f 184 // with a 1MHz clock rate
Chamilton09 0:52ce2a69824f 185 pc.printf("\nPress any button to program the AVR.\n");
Chamilton09 0:52ce2a69824f 186 char c = pc.getc();
Chamilton09 0:52ce2a69824f 187
Chamilton09 0:52ce2a69824f 188 spi.format(8,1); //SPI format: write data on rising edge, read on falling
Chamilton09 0:52ce2a69824f 189 //w/ a base clock value of zero
Chamilton09 0:52ce2a69824f 190 spi.frequency(TARGET_CLK >> 2);
Chamilton09 0:52ce2a69824f 191 //wait(0.5);
Chamilton09 0:52ce2a69824f 192 pc.printf("SPI interface started...\n");
Chamilton09 0:52ce2a69824f 193
Chamilton09 0:52ce2a69824f 194 // Select the device by seting chip select low
Chamilton09 0:52ce2a69824f 195 reset = 0;
Chamilton09 0:52ce2a69824f 196 wait(0.02);
Chamilton09 0:52ce2a69824f 197
Chamilton09 0:52ce2a69824f 198 if(enable_prog_mode() != 0) //Enable programming mode and check for errors
Chamilton09 0:52ce2a69824f 199 return -1;
Chamilton09 0:52ce2a69824f 200 spi.write(0x30);
Chamilton09 0:52ce2a69824f 201 spi.write(0x00);
Chamilton09 0:52ce2a69824f 202 spi.write(0x00);
Chamilton09 0:52ce2a69824f 203 pc.printf("SIGNATURE BYTE: %x\n",spi.write(0x00));
Chamilton09 0:52ce2a69824f 204 chip_erase();
Chamilton09 0:52ce2a69824f 205
Chamilton09 0:52ce2a69824f 206 write_lock_bits(0xFF); //1111 1111
Chamilton09 0:52ce2a69824f 207 write_fuse_bits(0x62); //1110 0010
Chamilton09 0:52ce2a69824f 208 write_fuse_bits_high(0xDF); //1101 1111
Chamilton09 0:52ce2a69824f 209 write_extended_fuse_bits(0xF9); //1111 1001
Chamilton09 0:52ce2a69824f 210
Chamilton09 0:52ce2a69824f 211 //Opening a file on local FS as in example code
Chamilton09 0:52ce2a69824f 212 pc.printf("Opening File...\n");
Chamilton09 0:52ce2a69824f 213 int flag = 0;
Chamilton09 0:52ce2a69824f 214 FILE *hex_file;
Chamilton09 0:52ce2a69824f 215 hex_file = fopen("/local/avr","r");
Chamilton09 0:52ce2a69824f 216 if(hex_file !=NULL)
Chamilton09 0:52ce2a69824f 217 {
Chamilton09 0:52ce2a69824f 218 uint16_t address = 0;
Chamilton09 0:52ce2a69824f 219 char temp;
Chamilton09 0:52ce2a69824f 220 temp = fgetc(hex_file);
Chamilton09 0:52ce2a69824f 221 while(flag == 0)
Chamilton09 0:52ce2a69824f 222 {
Chamilton09 0:52ce2a69824f 223 if(temp == ':')
Chamilton09 0:52ce2a69824f 224 {
Chamilton09 0:52ce2a69824f 225 uint8_t length = read_byte(hex_file);
Chamilton09 0:52ce2a69824f 226 if(length == 0){
Chamilton09 0:52ce2a69824f 227 flag = 1;
Chamilton09 0:52ce2a69824f 228 printf("EOF line reached.\n");
Chamilton09 0:52ce2a69824f 229 }
Chamilton09 0:52ce2a69824f 230 else{
Chamilton09 0:52ce2a69824f 231 fseek(hex_file, 6, SEEK_CUR); //2 if reading address
Chamilton09 0:52ce2a69824f 232
Chamilton09 0:52ce2a69824f 233 for(uint8_t i=0;i<length;i+=2){
Chamilton09 0:52ce2a69824f 234 uint8_t low_data = read_byte(hex_file);
Chamilton09 0:52ce2a69824f 235 uint8_t high_data = read_byte(hex_file);
Chamilton09 0:52ce2a69824f 236
Chamilton09 0:52ce2a69824f 237 //load data bytes here
Chamilton09 0:52ce2a69824f 238 load_prog_page(address, low_data, high_data);
Chamilton09 0:52ce2a69824f 239
Chamilton09 0:52ce2a69824f 240 address++;
Chamilton09 0:52ce2a69824f 241 }
Chamilton09 0:52ce2a69824f 242 while((temp = fgetc(hex_file)) != ':');
Chamilton09 0:52ce2a69824f 243 //pc.printf("\n");
Chamilton09 0:52ce2a69824f 244 }
Chamilton09 0:52ce2a69824f 245 }
Chamilton09 0:52ce2a69824f 246 else flag =1;
Chamilton09 0:52ce2a69824f 247 }
Chamilton09 0:52ce2a69824f 248 pc.printf("WRITE THE PAGE!\n");//write page here
Chamilton09 0:52ce2a69824f 249 write_prog_page(address);
Chamilton09 0:52ce2a69824f 250 fclose(hex_file);
Chamilton09 0:52ce2a69824f 251 }
Chamilton09 0:52ce2a69824f 252 else {
Chamilton09 0:52ce2a69824f 253 pc.printf("Failed to open the file...check the name.\n");
Chamilton09 0:52ce2a69824f 254 }
Chamilton09 0:52ce2a69824f 255 pc.printf("Successfully programmed!(hopefully...)\n");
Chamilton09 0:52ce2a69824f 256
Chamilton09 0:52ce2a69824f 257 // Deselect the device
Chamilton09 0:52ce2a69824f 258 reset = 1;
Chamilton09 0:52ce2a69824f 259 wait(0.02);
Chamilton09 0:52ce2a69824f 260 return 0;
Chamilton09 0:52ce2a69824f 261 }