MBED AVR ISP programmer. Targeted for ATMEGA1284p but should work for other AVR chips as well. Inspired by AVR_SPI_Programmer_v2 and AVR910.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
qiangbo
Date:
Thu Jan 05 02:44:12 2012 +0000
Commit message:
Initial version

Changed in this revision

AVRISP/AVRISP.cpp Show annotated file Show diff for this revision Revisions of this file
AVRISP/AVRISP.h Show annotated file Show diff for this revision Revisions of this file
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 064004c069be AVRISP/AVRISP.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AVRISP/AVRISP.cpp	Thu Jan 05 02:44:12 2012 +0000
@@ -0,0 +1,311 @@
+#include "AVRISP.h"
+
+// constructor
+AVRISP::AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset)
+{
+    spiPort = new SPI(mosi,miso,sclk);
+    spiPort->frequency(TARGET_CLK>>2);
+    spiPort->format(8,1);
+    resetPin = new DigitalOut(reset);
+}
+
+//A function to poll BSY to prevent loading a new instruction prematurely
+void AVRISP::StillProgramming() 
+{
+    int check = 1;
+    while(check == 1)
+    {
+        spiPort->write(0xF0);
+        spiPort->write(0x00);
+        spiPort->write(0x00);
+        check = spiPort->write(0x00); //read data byte out
+    }
+}
+
+// enable programming mode
+bool AVRISP::EnableProgrammingMode()
+{
+    int failed = 0;
+    
+    *resetPin = 1;
+    wait(0.02);
+    *resetPin = 0;
+    wait(0.02);
+    
+    while(failed < 5)               //loop to try to enable programming mode 5 times
+    {
+        spiPort->write(0xAC);
+        spiPort->write(0x53);
+        int echoBack= spiPort->write(0x00);
+        if(echoBack == 0x53)
+        {                           //if data read on 3rd byte load is 0x53
+            spiPort->write(0x00);   //programming mode was enabled...good job!
+            return true;
+        }
+        else
+        {
+            failed++;
+            *resetPin = 1;          //pulse reset and try again
+            *resetPin = 0;
+            wait(0.5);
+        }
+     }
+    return false;                   //Bummer...
+}
+
+void AVRISP::LeaveProgrammingMode()
+{
+    *resetPin = 1;
+    wait(0.02);
+}
+
+// read chip signature byte 1
+int AVRISP::ReadChipSignatureByte1()
+{
+    // read byte 1
+    spiPort->write(0x30);
+    spiPort->write(0x00);
+    spiPort->write(0x00);
+    int signatureByte1 = spiPort->write(0x00);
+    StillProgramming();
+    
+    return signatureByte1;
+}
+
+// read chip signature byte 2
+int AVRISP::ReadChipSignatureByte2()
+{
+    // read byte 1
+    spiPort->write(0x30);
+    spiPort->write(0x00);
+    spiPort->write(0x01);
+    int signatureByte2 = spiPort->write(0x00);
+    StillProgramming();
+    
+    return signatureByte2;
+}
+
+// read chip signature byte 3
+int AVRISP::ReadChipSignatureByte3()
+{
+    // read byte 1
+    spiPort->write(0x30);
+    spiPort->write(0x00);
+    spiPort->write(0x02);
+    int signatureByte3 = spiPort->write(0x00);
+    StillProgramming();
+    
+    return signatureByte3;
+}
+
+// erase chip
+void AVRISP::ChipErase()
+{
+    spiPort->write(0xAC);
+    spiPort->write(0x80);
+    spiPort->write(0x00);
+    spiPort->write(0x00);
+    StillProgramming();
+    *resetPin = 1;
+    wait(0.02);
+    *resetPin = 0;
+    wait(0.02);
+    EnableProgrammingMode();
+}
+
+// write fuse byte low
+void AVRISP::WriteFuseLow(uint8_t fuseLow)
+{
+    fuseLow = fuseLow&0xFF;
+    spiPort->write(0xAC);
+    spiPort->write(0xA0);
+    spiPort->write(0x00);
+    spiPort->write(fuseLow);
+    StillProgramming();
+}
+
+// read fuse byte low
+int AVRISP::ReadFuseLow()
+{
+    spiPort->write(0x50);
+    spiPort->write(0x00);
+    spiPort->write(0x00);
+    int readBack = spiPort->write(0x00);
+    StillProgramming();
+
+    return readBack;
+}
+
+// write fuse byte high
+void AVRISP::WriteFuseHigh(uint8_t fuseHigh)
+{
+    fuseHigh = fuseHigh&0xFF;
+    spiPort->write(0xAC);
+    spiPort->write(0xA8);
+    spiPort->write(0x00);
+    spiPort->write(fuseHigh);
+    StillProgramming();
+}
+
+// read fuse byte high
+int AVRISP::ReadFuseHigh()
+{
+    spiPort->write(0x58);
+    spiPort->write(0x08);
+    spiPort->write(0x00);
+    int readBack = spiPort->write(0x00);
+    StillProgramming();
+    
+    return readBack;
+}
+
+// write fuse byte extended
+void AVRISP::WriteFuseExtended(uint8_t fuseExtended)
+{
+    fuseExtended = fuseExtended&0xFF;
+    spiPort->write(0xAC);
+    spiPort->write(0xA4);
+    spiPort->write(0x00);
+    spiPort->write(fuseExtended);
+    StillProgramming();
+}
+
+// read fuse byte extended
+int AVRISP::ReadFuseExtended()
+{
+    spiPort->write(0x50);
+    spiPort->write(0x08);
+    spiPort->write(0x00);
+    int readBack = spiPort->write(0x00);
+    StillProgramming();
+    
+    return readBack;
+}
+
+// write lock byte
+void AVRISP::WriteLockByte(uint8_t lockByte)
+{
+    lockByte = lockByte&0xFF;
+    spiPort->write(0xAC);
+    spiPort->write(0xE0);
+    spiPort->write(0x00);
+    spiPort->write(lockByte);
+    StillProgramming();
+}
+
+// read lock byte
+int AVRISP::ReadLockByte()
+{
+    spiPort->write(0x58);
+    spiPort->write(0x00);
+    spiPort->write(0x00);
+    int readBack = spiPort->write(0x00);
+    StillProgramming();
+    
+    return readBack;
+}
+
+// write program page
+void AVRISP::WriteProgramPage(uint16_t addr)
+{
+    //write program memory page
+    spiPort->write(0x4C);
+    spiPort->write(MSB(addr));
+    spiPort->write(LSB(addr));
+    spiPort->write(0x00);
+    StillProgramming(); //make sure the operation worked
+}
+
+//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 AVRISP::LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData)//int addr_MSB, 
+{
+    //load program memory low byte (little endian)
+    spiPort->write(0x40);
+    spiPort->write(0x00);
+    spiPort->write(LSB(addr));
+    spiPort->write(lowData);
+    
+    //load program memory high byte
+    spiPort->write(0x48);
+    spiPort->write(0x00);
+    spiPort->write(LSB(addr));
+    spiPort->write(highData);
+   
+    // write page if 32 words have now been written
+    if(addr % MAX_PAGE_SIZE == (MAX_PAGE_SIZE-1))
+    {
+        WriteProgramPage(addr);
+    }
+}
+
+uint8_t AVRISP::ReadByte(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 AVRISP::ReadProgramFlash(uint8_t addrMSB, uint8_t addrLSB)
+{
+    spiPort->write(0x28);
+    spiPort->write(addrMSB);
+    spiPort->write(addrLSB);
+    spiPort->write(0x00);
+    spiPort->write(0x20);
+    spiPort->write(addrMSB);
+    spiPort->write(addrLSB);
+}
+
+// program flash
+bool AVRISP::ProgramFlash(char *hexFileName)
+{
+    int flag = 0;
+    FILE *hexFile;
+    hexFile = fopen(hexFileName,"r");
+    if(hexFile != NULL)
+    {    
+        uint16_t address = 0;
+        char temp;
+        temp = fgetc(hexFile);
+        while(flag == 0)
+        {
+            if(temp == ':')
+            {
+                uint8_t length = ReadByte(hexFile);
+                if(length == 0)
+                {
+                    flag = 1;
+                }
+                else
+                {
+                    fseek(hexFile,6,SEEK_CUR); //2 if reading address
+                    
+                    for(uint8_t i=0;i<length;i+=2)
+                    {
+                        uint8_t lowData = ReadByte(hexFile);
+                        uint8_t highData = ReadByte(hexFile);
+                       
+                        //load data bytes here
+                        LoadProgramPage(address,lowData,highData);
+                        
+                        address++;
+                    }
+                    while((temp = fgetc(hexFile)) != ':');            
+                }
+            }
+            else flag = 1;
+        }
+        WriteProgramPage(address);
+        fclose(hexFile);
+    }
+    else
+    {
+        return false;
+    }
+    
+    return true;
+}
+
diff -r 000000000000 -r 064004c069be AVRISP/AVRISP.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AVRISP/AVRISP.h	Thu Jan 05 02:44:12 2012 +0000
@@ -0,0 +1,66 @@
+//****************************************************************************/
+// Description:
+//
+//  Program AVR chips with the AVR910 ISP (in-system programming) protocol,
+//  using an mbed.
+//
+// This is a wrapper for AVR_ISP_Programmer_v2
+//
+//****************************************************************************/
+
+#ifndef AVRISP_H
+#define AVRISP_H
+
+//****************************************************************************/
+// Includes
+//****************************************************************************/
+#include "mbed.h"
+
+//****************************************************************************/
+// Definations for: ATMEGA1284p
+//****************************************************************************/
+#define SIGNATURE_BYTE_1    0x1E
+#define SIGNATURE_BYTE_2    0x97
+#define SIGNATURE_BYTE_3    0x05
+#define PAGE_SIZE           128
+#define NUM_PAGE            512
+
+//****************************************************************************/
+// Definations for programming
+//****************************************************************************/
+#define LSB(I) ((I) & 0xFF)
+#define MSB(I) (((I) & 0xF00) >> 8)
+#define TARGET_CLK 1000000L
+#define MAX_PAGE_SIZE (PAGE_SIZE >> 1) //divide max page size by 2 to get number of words per page
+
+class AVRISP
+{
+    public:
+        AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset);
+        bool EnableProgrammingMode();
+        void LeaveProgrammingMode();
+        int ReadChipSignatureByte1();
+        int ReadChipSignatureByte2();
+        int ReadChipSignatureByte3();
+        void StillProgramming();
+        void ChipErase();
+        void WriteFuseLow(uint8_t fuseLow);
+        int ReadFuseLow();
+        void WriteFuseHigh(uint8_t fuseHigh);
+        int ReadFuseHigh();
+        void WriteFuseExtended(uint8_t fuseExtended);
+        int ReadFuseExtended();
+        void WriteLockByte(uint8_t lockByte);
+        int ReadLockByte();
+        void WriteProgramPage(uint16_t addr);
+        void LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData);
+        uint8_t ReadByte(FILE *file);
+        void ReadProgramFlash(uint8_t addrMSB, uint8_t addrLSB);
+        bool ProgramFlash(char *hexFileName);
+
+    private:
+        SPI*        spiPort;
+        DigitalOut  *resetPin;
+};
+
+#endif
diff -r 000000000000 -r 064004c069be main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jan 05 02:44:12 2012 +0000
@@ -0,0 +1,65 @@
+#include "mbed.h"
+#include "AVRISP.h"
+
+#define FUSE_LOW            0xD0
+#define FUSE_HIGH           0xD9
+#define FUSE_EXTENDED       0xFF
+#define LOCK_BYTE           0xFF
+
+LocalFileSystem local("local");
+AVRISP avrisp(p11,p12,p13,p14);
+Serial pc(USBTX, USBRX);
+
+int main()
+{
+    bool ifSuccessful;
+    
+    pc.printf("Press any button to program the AVR.\n");
+    char c = pc.getc();
+    
+    ifSuccessful = avrisp.EnableProgrammingMode();
+    if(ifSuccessful)
+    {
+        pc.printf("Enter Programming Mode: Successful.\n");
+    }
+    else
+    {
+        pc.printf("Enter Programming Mode: Failed.\n");
+    }
+    
+    int signatureByte1 = avrisp.ReadChipSignatureByte1();
+    int signatureByte2 = avrisp.ReadChipSignatureByte2();
+    int signatureByte3 = avrisp.ReadChipSignatureByte3();
+    pc.printf("Chip signature is %x %x %x\n",signatureByte1,signatureByte2,signatureByte3);
+    
+    pc.printf("Erase Chip.\n");
+    avrisp.ChipErase();
+    
+    pc.printf("Write Fuse Low Byte.\n");
+    avrisp.WriteFuseLow(FUSE_LOW);
+    pc.printf("Fuse Low Byte Readback = %x.\n",avrisp.ReadFuseLow());
+    
+    pc.printf("Write Fuse High Byte.\n");
+    avrisp.WriteFuseLow(FUSE_HIGH);
+    pc.printf("Fuse High Byte Readback = %x.\n",avrisp.ReadFuseHigh());
+    
+    pc.printf("Write Fuse Extended Byte.\n");
+    avrisp.WriteFuseLow(FUSE_EXTENDED);
+    pc.printf("Fuse Extended Byte Readback = %x.\n",avrisp.ReadFuseExtended());
+    
+    pc.printf("Write Lock Byte.\n");
+    avrisp.WriteLockByte(LOCK_BYTE);
+    pc.printf("Lock Byte Readback = %x.\n",avrisp.ReadLockByte());    
+
+    ifSuccessful = avrisp.ProgramFlash("/local/avr1");
+    if(ifSuccessful)
+    {    
+        pc.printf("Program Flash: Successful.\n");
+    }
+    else
+    {
+        pc.printf("Program Flash: Failed.\n");
+    }
+
+    avrisp.LeaveProgrammingMode();
+}
diff -r 000000000000 -r 064004c069be mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Jan 05 02:44:12 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/078e4b97a13e