Want more features on Pastebin? Sign Up, it's FREE!
Guest

Arduino ISP with software spi

By: a guest on Jan 28th, 2012  |  syntax: C++  |  size: 11.54 KB  |  views: 1,126  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // this sketch turns the Arduino into a AVRISP
  2. // using the following pins:
  3. // 10: slave reset
  4. // 11: MOSI
  5. // 12: MISO
  6. // 13: SCK
  7.  
  8. // Put an LED (with resistor) on the following pins:
  9. // 9: Heartbeat - shows the programmer is running
  10. // 8: Error - Lights up if something goes wrong (use red if that makes sense)
  11. // 7: Programming - In communication with the slave
  12. //
  13. // October 2009 by David A. Mellis
  14. // - Added support for the read signature command
  15. //
  16. // February 2009 by Randall Bohn
  17. // - Added support for writing to EEPROM (what took so long?)
  18. // Windows users should consider WinAVR's avrdude instead of the
  19. // avrdude included with Arduino software.
  20. //
  21. // January 2008 by Randall Bohn
  22. // - Thanks to Amplificar for helping me with the STK500 protocol
  23. // - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
  24. // - The SPI functions herein were developed for the AVR910_ARD programmer
  25. // - More information at http://code.google.com/p/mega-isp
  26. #include <SPI.h>
  27. #include "pins_arduino.h"  // defines SS,MOSI,MISO,SCK
  28. #define RESET SS
  29.  
  30. #define LED_HB 9
  31. #define LED_ERR 8
  32. #define LED_PMODE 7
  33.  
  34. #define HWVER 2
  35. #define SWMAJ 1
  36. #define SWMIN 18
  37.  
  38. // STK Definitions
  39. #define STK_OK 0x10
  40. #define STK_FAILED 0x11
  41. #define STK_UNKNOWN 0x12
  42. #define STK_INSYNC 0x14
  43. #define STK_NOSYNC 0x15
  44. #define CRC_EOP 0x20 //ok it is a space...
  45.  
  46. void pulse(int pin, int times);
  47.  
  48. void setup() {
  49.   Serial.begin(19200);
  50.   pinMode(7, OUTPUT);
  51.   pulse(7, 2);
  52.   pinMode(8, OUTPUT);
  53.   pulse(8, 2);
  54.   pinMode(9, OUTPUT);
  55.   pulse(9, 2);
  56.   pinMode(SS, OUTPUT);
  57.   pinMode(MISO, INPUT);
  58.   pinMode(MOSI, OUTPUT);
  59.   pinMode(SCK, OUTPUT);
  60.  
  61. //  SPI.setClockDivider(SPI_CLOCK_DIV128);
  62.  
  63. }
  64.  
  65. int error=0;
  66. int pmode=0;
  67. // address for reading and writing, set by 'U' command
  68. int here;
  69. uint8_t buff[256]; // global block storage
  70.  
  71. #define beget16(addr) (*addr * 256 + *(addr+1) )
  72. typedef struct param {
  73.   uint8_t devicecode;
  74.   uint8_t revision;
  75.   uint8_t progtype;
  76.   uint8_t parmode;
  77.   uint8_t polling;
  78.   uint8_t selftimed;
  79.   uint8_t lockbytes;
  80.   uint8_t fusebytes;
  81.   int flashpoll;
  82.   int eeprompoll;
  83.   int pagesize;
  84.   int eepromsize;
  85.   int flashsize;
  86. }
  87. parameter;
  88.  
  89. parameter param;
  90.  
  91. // this provides a heartbeat on pin 9, so you can tell the software is running.
  92. uint8_t hbval=128;
  93. int8_t hbdelta=8;
  94. void heartbeat() {
  95.   if (hbval > 192) hbdelta = -hbdelta;
  96.   if (hbval < 32) hbdelta = -hbdelta;
  97.   hbval += hbdelta;
  98.   analogWrite(LED_HB, hbval);
  99.   delay(40);
  100. }
  101.  
  102.  
  103. void loop(void) {
  104.   // is pmode active?
  105.   if (pmode) digitalWrite(LED_PMODE, HIGH);
  106.   else digitalWrite(LED_PMODE, LOW);
  107.   // is there an error?
  108.   if (error) digitalWrite(LED_ERR, HIGH);
  109.   else digitalWrite(LED_ERR, LOW);
  110.  
  111.   // light the heartbeat LED
  112.   heartbeat();
  113.   if (Serial.available()) {
  114.     avrisp();
  115.   }
  116. }
  117.  
  118. uint8_t getch() {
  119.   while(!Serial.available());
  120.   return Serial.read();
  121. }
  122. void readbytes(int n) {
  123.   for (int x = 0; x < n; x++) {
  124.     buff[x] = Serial.read();
  125.   }
  126. }
  127.  
  128. #define PTIME 30
  129. void pulse(int pin, int times) {
  130.   do {
  131.     digitalWrite(pin, HIGH);
  132.     delay(PTIME);
  133.     digitalWrite(pin, LOW);
  134.     delay(PTIME);
  135.   }
  136.   while (times--);
  137. }
  138.  
  139. void spi_init() {
  140.   /*uint8_t x;
  141.   SPCR = 0x53;
  142.   x=SPSR;
  143.   x=SPDR;*/
  144. }
  145.  
  146. void spi_wait() {
  147.   do {
  148.   }
  149.   while (!(SPSR & (1 << SPIF)));
  150.   delay(100);
  151. }
  152. //unsigned char msk[] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
  153. unsigned char msk[] = {0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
  154. #define PCK() (bits[0] << 7 | bits[1] << 6 | bits[2] << 5 | bits[3] << 4 | bits[4] << 3 | bits[5] << 2 | bits[6] << 1 | bits[7])
  155. uint8_t spi_send(uint8_t b) {
  156.   uint8_t reply=0;
  157.   char bits[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  158.   /*SPDR=b;
  159.   spi_wait();
  160.   reply = SPDR;
  161.   return reply;*/
  162. //  digitalWrite(SS, LOW);
  163. //  delayMicroseconds(20);
  164. //cli();
  165.   for(uint8_t _bit = 0;_bit < 8;_bit++){
  166.    digitalWrite(MOSI, !!(b & msk[_bit]));
  167.    delayMicroseconds(50);
  168.    digitalWrite(SCK, HIGH);
  169.    delayMicroseconds(50);
  170.    bits[_bit] = digitalRead(MISO);
  171.    delayMicroseconds(50);
  172.    digitalWrite(SCK, LOW);
  173.    delayMicroseconds(50);
  174. //  delayMicroseconds(50);
  175.   }
  176. //  digitalWrite(SS, HIGH);
  177.   delayMicroseconds(50);
  178.   reply = PCK();
  179.   return reply;
  180.  
  181.  
  182. }
  183.  
  184. uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  185.   uint8_t n;
  186.   spi_send(a);
  187.   n=spi_send(b);
  188.   //if (n != a) error = -1;
  189.   n=spi_send(c);
  190.   return spi_send(d);
  191. }
  192.  
  193. void empty_reply() {
  194.   if (CRC_EOP == getch()) {
  195.     Serial.print((char)STK_INSYNC);
  196.     Serial.print((char)STK_OK);
  197.   }
  198.   else {
  199.     Serial.print((char)STK_NOSYNC);
  200.   }
  201. }
  202.  
  203. void breply(uint8_t b) {
  204.   if (CRC_EOP == getch()) {
  205.     Serial.print((char)STK_INSYNC);
  206.     Serial.print((char)b);
  207.     Serial.print((char)STK_OK);
  208.   }
  209.   else {
  210.     Serial.print((char)STK_NOSYNC);
  211.   }
  212. }
  213.  
  214. void get_version(uint8_t c) {
  215.   switch(c) {
  216.   case 0x80:
  217.     breply(HWVER);
  218.     break;
  219.   case 0x81:
  220.     breply(SWMAJ);
  221.     break;
  222.   case 0x82:
  223.     breply(SWMIN);
  224.     break;
  225.   case 0x93:
  226.     breply('S'); // serial programmer
  227.     break;
  228.   default:
  229.     breply(0);
  230.   }
  231. }
  232.  
  233. void set_parameters() {
  234.   // call this after reading paramter packet into buff[]
  235.   param.devicecode = buff[0];
  236.   param.revision = buff[1];
  237.   param.progtype = buff[2];
  238.   param.parmode = buff[3];
  239.   param.polling = buff[4];
  240.   param.selftimed = buff[5];
  241.   param.lockbytes = buff[6];
  242.   param.fusebytes = buff[7];
  243.   param.flashpoll = buff[8];
  244.   // ignore buff[9] (= buff[8])
  245.   //getch(); // discard second value
  246.  
  247.   // WARNING: not sure about the byte order of the following
  248.   // following are 16 bits (big endian)
  249.   param.eeprompoll = beget16(&buff[10]);
  250.   param.pagesize = beget16(&buff[12]);
  251.   param.eepromsize = beget16(&buff[14]);
  252.  
  253.   // 32 bits flashsize (big endian)
  254.   param.flashsize = buff[16] * 0x01000000
  255.     + buff[17] * 0x00010000
  256.     + buff[18] * 0x00000100
  257.     + buff[19];
  258.  
  259. }
  260.  
  261. void start_pmode() {
  262.   spi_init();
  263.   // following delays may not work on all targets...
  264.   pinMode(RESET, OUTPUT);
  265.   digitalWrite(RESET, HIGH);
  266.   pinMode(SCK, OUTPUT);
  267.   digitalWrite(SCK, LOW);
  268.   delay(50);
  269.   //delay(250);
  270.   digitalWrite(RESET, LOW);
  271.   delay(50);
  272. //delay(250);
  273.   pinMode(MISO, INPUT);
  274.   pinMode(MOSI, OUTPUT);
  275.   spi_transaction(0xAC, 0x53, 0x00, 0x00);
  276.   pmode = 1;
  277. }
  278.  
  279. void end_pmode() {
  280.   pinMode(MISO, INPUT);
  281.   pinMode(MOSI, INPUT);
  282.   pinMode(SCK, INPUT);
  283.   pinMode(RESET, INPUT);
  284.   pmode = 0;
  285. }
  286.  
  287. void universal() {
  288.   int w;
  289.   uint8_t ch;
  290.  
  291.   for (w = 0; w < 4; w++) {
  292.     buff[w] = getch();
  293.   }
  294.   ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
  295.   breply(ch);
  296. }
  297.  
  298. void flash(uint8_t hilo, int addr, uint8_t data) {
  299.   spi_transaction(0x40+8*hilo,
  300.   addr>>8 & 0xFF,
  301.   addr & 0xFF,
  302.   data);
  303. }
  304. void commit(int addr) {
  305.   spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
  306. }
  307.  
  308. //#define _current_page(x) (here & 0xFFFFE0)
  309. int current_page(int addr) {
  310.   if (param.pagesize == 32) return here & 0xFFFFFFF0;
  311.   if (param.pagesize == 64) return here & 0xFFFFFFE0;
  312.   if (param.pagesize == 128) return here & 0xFFFFFFC0;
  313.   if (param.pagesize == 256) return here & 0xFFFFFF80;
  314.   return here;
  315. }
  316. uint8_t write_flash(int length) {
  317.   if (param.pagesize < 1) return STK_FAILED;
  318.   //if (param.pagesize != 64) return STK_FAILED;
  319.   int page = current_page(here);
  320.   int x = 0;
  321.   while (x < length) {
  322.     if (page != current_page(here)) {
  323.       commit(page);
  324.       page = current_page(here);
  325.     }
  326.     flash(LOW, here, buff[x++]);
  327.     flash(HIGH, here, buff[x++]);
  328.     here++;
  329.   }
  330.  
  331.   commit(page);
  332.  
  333.   return STK_OK;
  334. }
  335.  
  336. uint8_t write_eeprom(int length) {
  337.   // here is a word address, so we use here*2
  338.   // this writes byte-by-byte,
  339.   // page writing may be faster (4 bytes at a time)
  340.   for (int x = 0; x < length; x++) {
  341.     spi_transaction(0xC0, 0x00, here*2+x, buff[x]);
  342.     delay(45);
  343.   }
  344.   return STK_OK;
  345. }
  346.  
  347. void program_page() {
  348.   char result = (char) STK_FAILED;
  349.   int length = 256 * getch() + getch();
  350.   if (length > 256) {
  351.       Serial.print((char) STK_FAILED);
  352.       return;
  353.   }
  354.   char memtype = getch();
  355.   for (int x = 0; x < length; x++) {
  356.     buff[x] = getch();
  357.   }
  358.   if (CRC_EOP == getch()) {
  359.     Serial.print((char) STK_INSYNC);
  360.     if (memtype == 'F') result = (char)write_flash(length);
  361.     if (memtype == 'E') result = (char)write_eeprom(length);
  362.     Serial.print(result);
  363.   }
  364.   else {
  365.     Serial.print((char) STK_NOSYNC);
  366.   }
  367. }
  368. uint8_t flash_read(uint8_t hilo, int addr) {
  369.   return spi_transaction(0x20 + hilo * 8,
  370.     (addr >> 8) & 0xFF,
  371.     addr & 0xFF,
  372.     0);
  373. }
  374.  
  375. char flash_read_page(int length) {
  376.   for (int x = 0; x < length; x+=2) {
  377.     uint8_t low = flash_read(LOW, here);
  378.     Serial.print((char) low);
  379.     uint8_t high = flash_read(HIGH, here);
  380.     Serial.print((char) high);
  381.     here++;
  382.   }
  383.   return STK_OK;
  384. }
  385.  
  386. char eeprom_read_page(int length) {
  387.   // here again we have a word address
  388.   for (int x = 0; x < length; x++) {
  389.     uint8_t ee = spi_transaction(0xA0, 0x00, here*2+x, 0xFF);
  390.     Serial.print((char) ee);
  391.   }
  392.   return STK_OK;
  393. }
  394.  
  395. void read_page() {
  396.   char result = (char)STK_FAILED;
  397.   int length = 256 * getch() + getch();
  398.   char memtype = getch();
  399.   if (CRC_EOP != getch()) {
  400.     Serial.print((char) STK_NOSYNC);
  401.     return;
  402.   }
  403.   Serial.print((char) STK_INSYNC);
  404.   if (memtype == 'F') result = flash_read_page(length);
  405.   if (memtype == 'E') result = eeprom_read_page(length);
  406.   Serial.print(result);
  407.   return;
  408. }
  409.  
  410. void read_signature() {
  411.   if (CRC_EOP != getch()) {
  412.     Serial.print((char) STK_NOSYNC);
  413.     return;
  414.   }
  415.   Serial.print((char) STK_INSYNC);
  416.   uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
  417.   Serial.print((char) high);
  418.   uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  419.   Serial.print((char) middle);
  420.   uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  421.   Serial.print((char) low);
  422.   Serial.print((char) STK_OK);
  423. }
  424. //////////////////////////////////////////
  425. //////////////////////////////////////////
  426.  
  427.  
  428. ////////////////////////////////////
  429. ////////////////////////////////////
  430. int avrisp() {
  431.   uint8_t data, low, high;
  432.   uint8_t ch = getch();
  433.   switch (ch) {
  434.   case '0': // signon
  435.     empty_reply();
  436.     break;
  437.   case '1':
  438.     if (getch() == CRC_EOP) {
  439.       Serial.print((char) STK_INSYNC);
  440.       Serial.print("AVR ISP");
  441.       Serial.print((char) STK_OK);
  442.     }
  443.     break;
  444.   case 'A':
  445.     get_version(getch());
  446.     break;
  447.   case 'B':
  448.     readbytes(20);
  449.     set_parameters();
  450.     empty_reply();
  451.     break;
  452.   case 'E': // extended parameters - ignore for now
  453.     readbytes(5);
  454.     empty_reply();
  455.     break;
  456.  
  457.   case 'P':
  458.     start_pmode();
  459.     empty_reply();
  460.     break;
  461.   case 'U':
  462.     here = getch() + 256 * getch();
  463.     empty_reply();
  464.     break;
  465.  
  466.   case 0x60: //STK_PROG_FLASH
  467.     low = getch();
  468.     high = getch();
  469.     empty_reply();
  470.     break;
  471.   case 0x61: //STK_PROG_DATA
  472.     data = getch();
  473.     empty_reply();
  474.     break;
  475.  
  476.   case 0x64: //STK_PROG_PAGE
  477.     program_page();
  478.     break;
  479.    
  480.   case 0x74: //STK_READ_PAGE
  481.     read_page();    
  482.     break;
  483.  
  484.   case 'V':
  485.     universal();
  486.     break;
  487.   case 'Q':
  488.     error=0;
  489.     end_pmode();
  490.     empty_reply();
  491.     break;
  492.    
  493.   case 0x75: //STK_READ_SIGN
  494.     read_signature();
  495.     break;
  496.  
  497.   // expecting a command, not CRC_EOP
  498.   // this is how we can get back in sync
  499.   case CRC_EOP:
  500.     Serial.print((char) STK_NOSYNC);
  501.     break;
  502.    
  503.   // anything else we will return STK_UNKNOWN
  504.   default:
  505.     if (CRC_EOP == getch())
  506.       Serial.print((char)STK_UNKNOWN);
  507.     else
  508.       Serial.print((char)STK_NOSYNC);
  509.   }
  510. }
clone this paste RAW Paste Data