Minimal Changes
This commit is contained in:
725
sketches/ArduinoISP/ArduinoISP.ino
Normal file
725
sketches/ArduinoISP/ArduinoISP.ino
Normal file
@ -0,0 +1,725 @@
|
||||
// ArduinoISP
|
||||
// Copyright (c) 2008-2011 Randall Bohn
|
||||
// If you require a license, see
|
||||
// http://www.opensource.org/licenses/bsd-license.php
|
||||
//
|
||||
// This sketch turns the Arduino into a AVRISP
|
||||
// using the following arduino pins:
|
||||
//
|
||||
// Pin 10 is used to reset the target microcontroller.
|
||||
//
|
||||
// By default, the hardware SPI pins MISO, MOSI and SCK pins are used
|
||||
// to communicate with the target. On all Arduinos, these pins can be found
|
||||
// on the ICSP/SPI header:
|
||||
//
|
||||
// MISO °. . 5V (!) Avoid this pin on Due, Zero...
|
||||
// SCK . . MOSI
|
||||
// . . GND
|
||||
//
|
||||
// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same pins
|
||||
// as digital pin 11, 12 and 13, respectively. That is why many tutorials
|
||||
// instruct you to hook up the target to these pins. If you find this wiring
|
||||
// more practical, have a define USE_OLD_STYLE_WIRING. This will work even
|
||||
// even when not using an Uno. (On an Uno this is not needed).
|
||||
//
|
||||
// Alternatively you can use any other digital pin by configuring software ('BitBanged')
|
||||
// SPI and having appropriate defines for PIN_MOSI, PIN_MISO and PIN_SCK.
|
||||
//
|
||||
// IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...)
|
||||
// as the programmer, make sure to not expose any of the programmer's pins to 5V.
|
||||
// A simple way to accomplish this is to power the complete system (programmer
|
||||
// and target) at 3V3.
|
||||
//
|
||||
// Put an LED (with resistor) on the following pins:
|
||||
// 9: Heartbeat - shows the programmer is running
|
||||
// 8: Error - Lights up if something goes wrong (use red if that makes sense)
|
||||
// 7: Programming - In communication with the slave
|
||||
//
|
||||
|
||||
#include "Arduino.h"
|
||||
#undef SERIAL
|
||||
|
||||
|
||||
#define PROG_FLICKER true
|
||||
|
||||
// Configure SPI clock (in Hz).
|
||||
// E.g. for an attiny @128 kHz: the datasheet states that both the high
|
||||
// and low spi clock pulse must be > 2 cpu cycles, so take 3 cycles i.e.
|
||||
// divide target f_cpu by 6:
|
||||
// #define SPI_CLOCK (128000/6)
|
||||
//
|
||||
// A clock slow enough for an attiny85 @ 1MHz, is a reasonable default:
|
||||
|
||||
#define SPI_CLOCK (20000000/6)
|
||||
|
||||
|
||||
// Select hardware or software SPI, depending on SPI clock.
|
||||
// Currently only for AVR, for other archs (Due, Zero,...),
|
||||
// hardware SPI is probably too fast anyway.
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
|
||||
#if SPI_CLOCK > (F_CPU / 128)
|
||||
#define USE_HARDWARE_SPI
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Configure which pins to use:
|
||||
|
||||
// The standard pin configuration.
|
||||
#ifndef ARDUINO_HOODLOADER2
|
||||
|
||||
#define RESET 10 // Use pin 10 to reset the target rather than SS
|
||||
#define LED_HB 9
|
||||
#define LED_ERR 8
|
||||
#define LED_PMODE 7
|
||||
|
||||
// Uncomment following line to use the old Uno style wiring
|
||||
// (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due...
|
||||
|
||||
// #define USE_OLD_STYLE_WIRING
|
||||
|
||||
#ifdef USE_OLD_STYLE_WIRING
|
||||
|
||||
#define PIN_MOSI 11
|
||||
#define PIN_MISO 12
|
||||
#define PIN_SCK 13
|
||||
|
||||
#endif
|
||||
|
||||
// HOODLOADER2 means running sketches on the atmega16u2
|
||||
// serial converter chips on Uno or Mega boards.
|
||||
// We must use pins that are broken out:
|
||||
#else
|
||||
|
||||
#define RESET 4
|
||||
#define LED_HB 7
|
||||
#define LED_ERR 6
|
||||
#define LED_PMODE 5
|
||||
|
||||
#endif
|
||||
|
||||
// By default, use hardware SPI pins:
|
||||
#ifndef PIN_MOSI
|
||||
#define PIN_MOSI MOSI
|
||||
#endif
|
||||
|
||||
#ifndef PIN_MISO
|
||||
#define PIN_MISO MISO
|
||||
#endif
|
||||
|
||||
#ifndef PIN_SCK
|
||||
#define PIN_SCK SCK
|
||||
#endif
|
||||
|
||||
// Force bitbanged SPI if not using the hardware SPI pins:
|
||||
#if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK)
|
||||
#undef USE_HARDWARE_SPI
|
||||
#endif
|
||||
|
||||
|
||||
// Configure the serial port to use.
|
||||
//
|
||||
// Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one:
|
||||
// - it does not autoreset (except for the magic baud rate of 1200).
|
||||
// - it is more reliable because of USB handshaking.
|
||||
//
|
||||
// Leonardo and similar have an USB virtual serial port: 'Serial'.
|
||||
// Due and Zero have an USB virtual serial port: 'SerialUSB'.
|
||||
//
|
||||
// On the Due and Zero, 'Serial' can be used too, provided you disable autoreset.
|
||||
// To use 'Serial': #define SERIAL Serial
|
||||
|
||||
#ifdef SERIAL_PORT_USBVIRTUAL
|
||||
#define SERIAL SERIAL_PORT_USBVIRTUAL
|
||||
#else
|
||||
#define SERIAL Serial
|
||||
#endif
|
||||
|
||||
|
||||
// Configure the baud rate:
|
||||
|
||||
// #define BAUDRATE 19200
|
||||
#define BAUDRATE 115200
|
||||
// #define BAUDRATE 1000000
|
||||
|
||||
|
||||
#define HWVER 2
|
||||
#define SWMAJ 1
|
||||
#define SWMIN 18
|
||||
|
||||
// STK Definitions
|
||||
#define STK_OK 0x10
|
||||
#define STK_FAILED 0x11
|
||||
#define STK_UNKNOWN 0x12
|
||||
#define STK_INSYNC 0x14
|
||||
#define STK_NOSYNC 0x15
|
||||
#define CRC_EOP 0x20 //ok it is a space...
|
||||
|
||||
void pulse(int pin, int times);
|
||||
|
||||
#ifdef USE_HARDWARE_SPI
|
||||
#include "SPI.h"
|
||||
#else
|
||||
|
||||
#define SPI_MODE0 0x00
|
||||
|
||||
class SPISettings {
|
||||
public:
|
||||
// clock is in Hz
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clock(clock){
|
||||
(void) bitOrder;
|
||||
(void) dataMode;
|
||||
};
|
||||
|
||||
private:
|
||||
uint32_t clock;
|
||||
|
||||
friend class BitBangedSPI;
|
||||
};
|
||||
|
||||
class BitBangedSPI {
|
||||
public:
|
||||
void begin() {
|
||||
digitalWrite(PIN_SCK, LOW);
|
||||
digitalWrite(PIN_MOSI, LOW);
|
||||
pinMode(PIN_SCK, OUTPUT);
|
||||
pinMode(PIN_MOSI, OUTPUT);
|
||||
pinMode(PIN_MISO, INPUT);
|
||||
}
|
||||
|
||||
void beginTransaction(SPISettings settings) {
|
||||
pulseWidth = (500000 + settings.clock - 1) / settings.clock;
|
||||
if (pulseWidth == 0)
|
||||
pulseWidth = 1;
|
||||
}
|
||||
|
||||
void end() {}
|
||||
|
||||
uint8_t transfer (uint8_t b) {
|
||||
for (unsigned int i = 0; i < 8; ++i) {
|
||||
digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW);
|
||||
digitalWrite(PIN_SCK, HIGH);
|
||||
delayMicroseconds(pulseWidth);
|
||||
b = (b << 1) | digitalRead(PIN_MISO);
|
||||
digitalWrite(PIN_SCK, LOW); // slow pulse
|
||||
delayMicroseconds(pulseWidth);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long pulseWidth; // in microseconds
|
||||
};
|
||||
|
||||
static BitBangedSPI SPI;
|
||||
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
SERIAL.begin(BAUDRATE);
|
||||
|
||||
pinMode(LED_PMODE, OUTPUT);
|
||||
pulse(LED_PMODE, 2);
|
||||
pinMode(LED_ERR, OUTPUT);
|
||||
pulse(LED_ERR, 2);
|
||||
pinMode(LED_HB, OUTPUT);
|
||||
pulse(LED_HB, 2);
|
||||
|
||||
}
|
||||
|
||||
int error = 0;
|
||||
int pmode = 0;
|
||||
// address for reading and writing, set by 'U' command
|
||||
unsigned int here;
|
||||
uint8_t buff[256]; // global block storage
|
||||
|
||||
#define beget16(addr) (*addr * 256 + *(addr+1) )
|
||||
typedef struct param {
|
||||
uint8_t devicecode;
|
||||
uint8_t revision;
|
||||
uint8_t progtype;
|
||||
uint8_t parmode;
|
||||
uint8_t polling;
|
||||
uint8_t selftimed;
|
||||
uint8_t lockbytes;
|
||||
uint8_t fusebytes;
|
||||
uint8_t flashpoll;
|
||||
uint16_t eeprompoll;
|
||||
uint16_t pagesize;
|
||||
uint16_t eepromsize;
|
||||
uint32_t flashsize;
|
||||
}
|
||||
parameter;
|
||||
|
||||
parameter param;
|
||||
|
||||
// this provides a heartbeat on pin 9, so you can tell the software is running.
|
||||
uint8_t hbval = 128;
|
||||
int8_t hbdelta = 8;
|
||||
void heartbeat() {
|
||||
static unsigned long last_time = 0;
|
||||
unsigned long now = millis();
|
||||
if ((now - last_time) < 40)
|
||||
return;
|
||||
last_time = now;
|
||||
if (hbval > 192) hbdelta = -hbdelta;
|
||||
if (hbval < 32) hbdelta = -hbdelta;
|
||||
hbval += hbdelta;
|
||||
analogWrite(LED_HB, hbval);
|
||||
}
|
||||
|
||||
static bool rst_active_high;
|
||||
|
||||
void reset_target(bool reset) {
|
||||
digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW);
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
// is pmode active?
|
||||
if (pmode) {
|
||||
digitalWrite(LED_PMODE, HIGH);
|
||||
} else {
|
||||
digitalWrite(LED_PMODE, LOW);
|
||||
}
|
||||
// is there an error?
|
||||
if (error) {
|
||||
digitalWrite(LED_ERR, HIGH);
|
||||
} else {
|
||||
digitalWrite(LED_ERR, LOW);
|
||||
}
|
||||
|
||||
// light the heartbeat LED
|
||||
heartbeat();
|
||||
if (SERIAL.available()) {
|
||||
avrisp();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getch() {
|
||||
while (!SERIAL.available());
|
||||
return SERIAL.read();
|
||||
}
|
||||
void fill(int n) {
|
||||
for (int x = 0; x < n; x++) {
|
||||
buff[x] = getch();
|
||||
}
|
||||
}
|
||||
|
||||
#define PTIME 30
|
||||
void pulse(int pin, int times) {
|
||||
do {
|
||||
digitalWrite(pin, HIGH);
|
||||
delay(PTIME);
|
||||
digitalWrite(pin, LOW);
|
||||
delay(PTIME);
|
||||
} while (times--);
|
||||
}
|
||||
|
||||
void prog_lamp(int state) {
|
||||
if (PROG_FLICKER) {
|
||||
digitalWrite(LED_PMODE, state);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||
SPI.transfer(a);
|
||||
SPI.transfer(b);
|
||||
SPI.transfer(c);
|
||||
return SPI.transfer(d);
|
||||
}
|
||||
|
||||
void empty_reply() {
|
||||
if (CRC_EOP == getch()) {
|
||||
SERIAL.print((char)STK_INSYNC);
|
||||
SERIAL.print((char)STK_OK);
|
||||
} else {
|
||||
error++;
|
||||
SERIAL.print((char)STK_NOSYNC);
|
||||
}
|
||||
}
|
||||
|
||||
void breply(uint8_t b) {
|
||||
if (CRC_EOP == getch()) {
|
||||
SERIAL.print((char)STK_INSYNC);
|
||||
SERIAL.print((char)b);
|
||||
SERIAL.print((char)STK_OK);
|
||||
} else {
|
||||
error++;
|
||||
SERIAL.print((char)STK_NOSYNC);
|
||||
}
|
||||
}
|
||||
|
||||
void get_version(uint8_t c) {
|
||||
switch (c) {
|
||||
case 0x80:
|
||||
breply(HWVER);
|
||||
break;
|
||||
case 0x81:
|
||||
breply(SWMAJ);
|
||||
break;
|
||||
case 0x82:
|
||||
breply(SWMIN);
|
||||
break;
|
||||
case 0x93:
|
||||
breply('S'); // serial programmer
|
||||
break;
|
||||
default:
|
||||
breply(0);
|
||||
}
|
||||
}
|
||||
|
||||
void set_parameters() {
|
||||
// call this after reading paramter packet into buff[]
|
||||
param.devicecode = buff[0];
|
||||
param.revision = buff[1];
|
||||
param.progtype = buff[2];
|
||||
param.parmode = buff[3];
|
||||
param.polling = buff[4];
|
||||
param.selftimed = buff[5];
|
||||
param.lockbytes = buff[6];
|
||||
param.fusebytes = buff[7];
|
||||
param.flashpoll = buff[8];
|
||||
// ignore buff[9] (= buff[8])
|
||||
// following are 16 bits (big endian)
|
||||
param.eeprompoll = beget16(&buff[10]);
|
||||
param.pagesize = beget16(&buff[12]);
|
||||
param.eepromsize = beget16(&buff[14]);
|
||||
|
||||
// 32 bits flashsize (big endian)
|
||||
param.flashsize = buff[16] * 0x01000000
|
||||
+ buff[17] * 0x00010000
|
||||
+ buff[18] * 0x00000100
|
||||
+ buff[19];
|
||||
|
||||
// avr devices have active low reset, at89sx are active high
|
||||
rst_active_high = (param.devicecode >= 0xe0);
|
||||
}
|
||||
|
||||
void start_pmode() {
|
||||
|
||||
// Reset target before driving PIN_SCK or PIN_MOSI
|
||||
|
||||
// SPI.begin() will configure SS as output,
|
||||
// so SPI master mode is selected.
|
||||
// We have defined RESET as pin 10,
|
||||
// which for many arduino's is not the SS pin.
|
||||
// So we have to configure RESET as output here,
|
||||
// (reset_target() first sets the correct level)
|
||||
reset_target(true);
|
||||
pinMode(RESET, OUTPUT);
|
||||
SPI.begin();
|
||||
SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));
|
||||
|
||||
// See avr datasheets, chapter "SERIAL_PRG Programming Algorithm":
|
||||
|
||||
// Pulse RESET after PIN_SCK is low:
|
||||
digitalWrite(PIN_SCK, LOW);
|
||||
delay(20); // discharge PIN_SCK, value arbitrally chosen
|
||||
reset_target(false);
|
||||
// Pulse must be minimum 2 target CPU clock cycles
|
||||
// so 100 usec is ok for CPU speeds above 20KHz
|
||||
delayMicroseconds(100);
|
||||
reset_target(true);
|
||||
|
||||
// Send the enable programming command:
|
||||
delay(50); // datasheet: must be > 20 msec
|
||||
spi_transaction(0xAC, 0x53, 0x00, 0x00);
|
||||
pmode = 1;
|
||||
}
|
||||
|
||||
void end_pmode() {
|
||||
SPI.end();
|
||||
// We're about to take the target out of reset
|
||||
// so configure SPI pins as input
|
||||
pinMode(PIN_MOSI, INPUT);
|
||||
pinMode(PIN_SCK, INPUT);
|
||||
reset_target(false);
|
||||
pinMode(RESET, INPUT);
|
||||
pmode = 0;
|
||||
}
|
||||
|
||||
void universal() {
|
||||
uint8_t ch;
|
||||
|
||||
fill(4);
|
||||
ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
|
||||
breply(ch);
|
||||
}
|
||||
|
||||
void flash(uint8_t hilo, unsigned int addr, uint8_t data) {
|
||||
spi_transaction(0x40 + 8 * hilo,
|
||||
addr >> 8 & 0xFF,
|
||||
addr & 0xFF,
|
||||
data);
|
||||
}
|
||||
void commit(unsigned int addr) {
|
||||
if (PROG_FLICKER) {
|
||||
prog_lamp(LOW);
|
||||
}
|
||||
spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
|
||||
if (PROG_FLICKER) {
|
||||
delay(PTIME);
|
||||
prog_lamp(HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int current_page() {
|
||||
if (param.pagesize == 32) {
|
||||
return here & 0xFFFFFFF0;
|
||||
}
|
||||
if (param.pagesize == 64) {
|
||||
return here & 0xFFFFFFE0;
|
||||
}
|
||||
if (param.pagesize == 128) {
|
||||
return here & 0xFFFFFFC0;
|
||||
}
|
||||
if (param.pagesize == 256) {
|
||||
return here & 0xFFFFFF80;
|
||||
}
|
||||
return here;
|
||||
}
|
||||
|
||||
|
||||
void write_flash(int length) {
|
||||
fill(length);
|
||||
if (CRC_EOP == getch()) {
|
||||
SERIAL.print((char) STK_INSYNC);
|
||||
SERIAL.print((char) write_flash_pages(length));
|
||||
} else {
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t write_flash_pages(int length) {
|
||||
int x = 0;
|
||||
unsigned int page = current_page();
|
||||
while (x < length) {
|
||||
if (page != current_page()) {
|
||||
commit(page);
|
||||
page = current_page();
|
||||
}
|
||||
flash(LOW, here, buff[x++]);
|
||||
flash(HIGH, here, buff[x++]);
|
||||
here++;
|
||||
}
|
||||
|
||||
commit(page);
|
||||
|
||||
return STK_OK;
|
||||
}
|
||||
|
||||
#define EECHUNK (32)
|
||||
uint8_t write_eeprom(unsigned int length) {
|
||||
// here is a word address, get the byte address
|
||||
unsigned int start = here * 2;
|
||||
unsigned int remaining = length;
|
||||
if (length > param.eepromsize) {
|
||||
error++;
|
||||
return STK_FAILED;
|
||||
}
|
||||
while (remaining > EECHUNK) {
|
||||
write_eeprom_chunk(start, EECHUNK);
|
||||
start += EECHUNK;
|
||||
remaining -= EECHUNK;
|
||||
}
|
||||
write_eeprom_chunk(start, remaining);
|
||||
return STK_OK;
|
||||
}
|
||||
// write (length) bytes, (start) is a byte address
|
||||
uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) {
|
||||
// this writes byte-by-byte,
|
||||
// page writing may be faster (4 bytes at a time)
|
||||
fill(length);
|
||||
prog_lamp(LOW);
|
||||
for (unsigned int x = 0; x < length; x++) {
|
||||
unsigned int addr = start + x;
|
||||
spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]);
|
||||
delay(45);
|
||||
}
|
||||
prog_lamp(HIGH);
|
||||
return STK_OK;
|
||||
}
|
||||
|
||||
void program_page() {
|
||||
char result = (char) STK_FAILED;
|
||||
unsigned int length = 256 * getch();
|
||||
length += getch();
|
||||
char memtype = getch();
|
||||
// flash memory @here, (length) bytes
|
||||
if (memtype == 'F') {
|
||||
write_flash(length);
|
||||
return;
|
||||
}
|
||||
if (memtype == 'E') {
|
||||
result = (char)write_eeprom(length);
|
||||
if (CRC_EOP == getch()) {
|
||||
SERIAL.print((char) STK_INSYNC);
|
||||
SERIAL.print(result);
|
||||
} else {
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
}
|
||||
return;
|
||||
}
|
||||
SERIAL.print((char)STK_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t flash_read(uint8_t hilo, unsigned int addr) {
|
||||
return spi_transaction(0x20 + hilo * 8,
|
||||
(addr >> 8) & 0xFF,
|
||||
addr & 0xFF,
|
||||
0);
|
||||
}
|
||||
|
||||
char flash_read_page(int length) {
|
||||
for (int x = 0; x < length; x += 2) {
|
||||
uint8_t low = flash_read(LOW, here);
|
||||
SERIAL.print((char) low);
|
||||
uint8_t high = flash_read(HIGH, here);
|
||||
SERIAL.print((char) high);
|
||||
here++;
|
||||
}
|
||||
return STK_OK;
|
||||
}
|
||||
|
||||
char eeprom_read_page(int length) {
|
||||
// here again we have a word address
|
||||
int start = here * 2;
|
||||
for (int x = 0; x < length; x++) {
|
||||
int addr = start + x;
|
||||
uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF);
|
||||
SERIAL.print((char) ee);
|
||||
}
|
||||
return STK_OK;
|
||||
}
|
||||
|
||||
void read_page() {
|
||||
char result = (char)STK_FAILED;
|
||||
int length = 256 * getch();
|
||||
length += getch();
|
||||
char memtype = getch();
|
||||
if (CRC_EOP != getch()) {
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
return;
|
||||
}
|
||||
SERIAL.print((char) STK_INSYNC);
|
||||
if (memtype == 'F') result = flash_read_page(length);
|
||||
if (memtype == 'E') result = eeprom_read_page(length);
|
||||
SERIAL.print(result);
|
||||
}
|
||||
|
||||
void read_signature() {
|
||||
if (CRC_EOP != getch()) {
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
return;
|
||||
}
|
||||
SERIAL.print((char) STK_INSYNC);
|
||||
uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
|
||||
SERIAL.print((char) high);
|
||||
uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
|
||||
SERIAL.print((char) middle);
|
||||
uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
|
||||
SERIAL.print((char) low);
|
||||
SERIAL.print((char) STK_OK);
|
||||
}
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
////////////////////////////////////
|
||||
void avrisp() {
|
||||
uint8_t ch = getch();
|
||||
switch (ch) {
|
||||
case '0': // signon
|
||||
error = 0;
|
||||
empty_reply();
|
||||
break;
|
||||
case '1':
|
||||
if (getch() == CRC_EOP) {
|
||||
SERIAL.print((char) STK_INSYNC);
|
||||
SERIAL.print("AVR ISP");
|
||||
SERIAL.print((char) STK_OK);
|
||||
}
|
||||
else {
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
get_version(getch());
|
||||
break;
|
||||
case 'B':
|
||||
fill(20);
|
||||
set_parameters();
|
||||
empty_reply();
|
||||
break;
|
||||
case 'E': // extended parameters - ignore for now
|
||||
fill(5);
|
||||
empty_reply();
|
||||
break;
|
||||
case 'P':
|
||||
if (!pmode)
|
||||
start_pmode();
|
||||
empty_reply();
|
||||
break;
|
||||
case 'U': // set address (word)
|
||||
here = getch();
|
||||
here += 256 * getch();
|
||||
empty_reply();
|
||||
break;
|
||||
|
||||
case 0x60: //STK_PROG_FLASH
|
||||
getch(); // low addr
|
||||
getch(); // high addr
|
||||
empty_reply();
|
||||
break;
|
||||
case 0x61: //STK_PROG_DATA
|
||||
getch(); // data
|
||||
empty_reply();
|
||||
break;
|
||||
|
||||
case 0x64: //STK_PROG_PAGE
|
||||
program_page();
|
||||
break;
|
||||
|
||||
case 0x74: //STK_READ_PAGE 't'
|
||||
read_page();
|
||||
break;
|
||||
|
||||
case 'V': //0x56
|
||||
universal();
|
||||
break;
|
||||
case 'Q': //0x51
|
||||
error = 0;
|
||||
end_pmode();
|
||||
empty_reply();
|
||||
break;
|
||||
|
||||
case 0x75: //STK_READ_SIGN 'u'
|
||||
read_signature();
|
||||
break;
|
||||
|
||||
// expecting a command, not CRC_EOP
|
||||
// this is how we can get back in sync
|
||||
case CRC_EOP:
|
||||
error++;
|
||||
SERIAL.print((char) STK_NOSYNC);
|
||||
break;
|
||||
|
||||
// anything else we will return STK_UNKNOWN
|
||||
default:
|
||||
error++;
|
||||
if (CRC_EOP == getch())
|
||||
SERIAL.print((char)STK_UNKNOWN);
|
||||
else
|
||||
SERIAL.print((char)STK_NOSYNC);
|
||||
}
|
||||
}
|
||||
|
23
sketches/led-driver/Makefile
Normal file
23
sketches/led-driver/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
CFLAGS = -O3 -Wall --std=c11
|
||||
CHIP = 328p
|
||||
SOURCE_FILES = $(wildcard *.c)
|
||||
OBJ_FILES = $(SOURCE_FILES:%.c=%.o)
|
||||
BIN = led-driver.bin
|
||||
HEX = led-driver.hex
|
||||
|
||||
default: $(HEX)
|
||||
|
||||
%.o: %.c
|
||||
avr-gcc $(CFLAGS) -mmcu=atmega$(CHIP) -o $@ $<
|
||||
|
||||
$(BIN): $(OBJ_FILES)
|
||||
avr-gcc $(CFLAGS) -o $@ $^
|
||||
|
||||
$(HEX): $(BIN)
|
||||
avr-objcopy -O ihex -j .text -j .data $^ $@
|
||||
|
||||
flash: $(HEX)
|
||||
avrdude -p m$(CHIP) -c arduino -B 115200 -P /dev/ttyACM0 -v -v -e flash:w:$(HEX):a
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJ_FILES) $(BIN) $(HEX)
|
81
sketches/led-driver/a.hex
Normal file
81
sketches/led-driver/a.hex
Normal file
@ -0,0 +1,81 @@
|
||||
:100000000C9434000C943E000C943E000C943E0082
|
||||
:100010000C943E000C943E000C943E000C943E0068
|
||||
:100020000C943E000C943E000C943E000C943E0058
|
||||
:100030000C943E000C943E000C943E000C943E0048
|
||||
:100040000C943E000C943E000C943E000C943E0038
|
||||
:100050000C943E000C943E000C943E000C943E0028
|
||||
:100060000C943E000C943E0011241FBECFEFD8E04C
|
||||
:10007000DEBFCDBF0E9440000C9477020C940000BC
|
||||
:1000800081E087B988B9000000000000000000008E
|
||||
:10009000000018B800000000000000000000000090
|
||||
:1000A0000000000000000000000000000000000050
|
||||
:1000B000000088B9000000000000000000000000FF
|
||||
:1000C00018B8000000000000000000000000000060
|
||||
:1000D0000000000000000000000000000000000020
|
||||
:1000E00088B900000000000000000000000018B8FF
|
||||
:1000F0000000000000000000000000000000000000
|
||||
:10010000000000000000000000000000000088B9AE
|
||||
:1001100000000000000000000000000018B800000F
|
||||
:1001200000000000000000000000000000000000CF
|
||||
:1001300000000000000000000000000088B900007E
|
||||
:100140000000000000000000000018B800000000DF
|
||||
:10015000000000000000000000000000000000009F
|
||||
:100160000000000000000000000088B9000000004E
|
||||
:10017000000000000000000018B8000000000000AF
|
||||
:10018000000000000000000000000000000000006F
|
||||
:10019000000000000000000088B90000000000001E
|
||||
:1001A00000000000000018B800000000000000007F
|
||||
:1001B000000000000000000000000000000000003F
|
||||
:1001C00000000000000088B90000000000000000EE
|
||||
:1001D0000000000018B8000000000000000000004F
|
||||
:1001E000000000000000000000000000000000000F
|
||||
:1001F0000000000088B900000000000000000000BE
|
||||
:10020000000018B80000000000000000000000001E
|
||||
:1002100000000000000000000000000000000000DE
|
||||
:10022000000088B90000000000000000000000008D
|
||||
:1002300018B80000000000000000000000000000EE
|
||||
:1002400000000000000000000000000000000000AE
|
||||
:1002500088B900000000000000000000000018B88D
|
||||
:10026000000000000000000000000000000000008E
|
||||
:10027000000000000000000000000000000088B93D
|
||||
:1002800000000000000000000000000018B800009E
|
||||
:10029000000000000000000000000000000000005E
|
||||
:1002A00000000000000000000000000088B900000D
|
||||
:1002B0000000000000000000000018B8000000006E
|
||||
:1002C000000000000000000000000000000000002E
|
||||
:1002D0000000000000000000000088B900000000DD
|
||||
:1002E000000000000000000018B80000000000003E
|
||||
:1002F00000000000000000000000000000000000FE
|
||||
:10030000000000000000000088B9000000000000AC
|
||||
:1003100000000000000018B800000000000000000D
|
||||
:1003200000000000000000000000000000000000CD
|
||||
:1003300000000000000088B900000000000000007C
|
||||
:100340000000000018B800000000000000000000DD
|
||||
:10035000000000000000000000000000000000009D
|
||||
:100360000000000088B9000000000000000000004C
|
||||
:10037000000000000000000000000000000000007D
|
||||
:10038000000018B80000000000000000000000009D
|
||||
:100390000000000088B9000000000000000000001C
|
||||
:1003A000000000000000000000000000000000004D
|
||||
:1003B000000018B80000000000000000000000006D
|
||||
:1003C0000000000088B900000000000000000000EC
|
||||
:1003D000000000000000000000000000000000001D
|
||||
:1003E000000018B80000000000000000000000003D
|
||||
:1003F0000000000088B900000000000000000000BC
|
||||
:1004000000000000000000000000000000000000EC
|
||||
:10041000000018B80000000000000000000000000C
|
||||
:100420000000000088B9000000000000000000008B
|
||||
:1004300000000000000000000000000000000000BC
|
||||
:10044000000018B8000000000000000000000000DC
|
||||
:100450000000000088B9000000000000000000005B
|
||||
:10046000000000000000000000000000000000008C
|
||||
:10047000000018B8000000000000000000000000AC
|
||||
:100480000000000088B9000000000000000000002B
|
||||
:10049000000000000000000000000000000000005C
|
||||
:1004A000000018B80000000000000000000000007C
|
||||
:1004B0000000000088B900000000000000000000FB
|
||||
:1004C000000000000000000000000000000000002C
|
||||
:1004D000000018B80000000000000000000000004C
|
||||
:1004E0000000000090E19A95F1F700C0CBCDF894A0
|
||||
:0204F000FFCF3C
|
||||
:00000001FF
|
BIN
sketches/led-driver/a.out
Executable file
BIN
sketches/led-driver/a.out
Executable file
Binary file not shown.
BIN
sketches/led-driver/led-driver.bin
Executable file
BIN
sketches/led-driver/led-driver.bin
Executable file
Binary file not shown.
54
sketches/led-driver/led-driver.c
Normal file
54
sketches/led-driver/led-driver.c
Normal file
@ -0,0 +1,54 @@
|
||||
#define F_CPU 1000000UL
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
/*
|
||||
// f=20MHz -> T=0,05 µs
|
||||
uint8_t T0H = 6; // == 0.3 µs ~ 0.4 µs (+- 150ns) == [0.25, 0.55] µs
|
||||
uint8_t T1H = 14; // == 0.7 µs ~ 0.8 µs (+- 150ns) == [0.65, 0.95] µs
|
||||
uint8_t T0L = 15; // == 0.75 µs ~ 0.85µs (+- 150ns) == [0.70, 1.00] µs
|
||||
uint8_t T1L = 8; // == 0.35 µs ~ 0.45µs (+- 150ns) == [0.30, 0.60] µs
|
||||
uint8_t RES = 51; // > 50 µs
|
||||
*/
|
||||
|
||||
#define wait6 __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")
|
||||
#define wait8 __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")
|
||||
#define wait14 __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")
|
||||
#define wait15 __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t")
|
||||
|
||||
inline void writeZero() {
|
||||
PORTB = 1;
|
||||
wait6;
|
||||
PORTB = 0;
|
||||
wait15;
|
||||
}
|
||||
|
||||
inline void writeOne() {
|
||||
PORTB = 1;
|
||||
wait14;
|
||||
PORTB = 0;
|
||||
wait8;
|
||||
}
|
||||
|
||||
int main2() {
|
||||
DDRB = 1; // PORT C0 output
|
||||
|
||||
do{
|
||||
writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();
|
||||
writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();writeZero();
|
||||
writeOne();writeOne();writeOne();writeOne();writeOne();writeOne();writeOne();writeOne();
|
||||
_delay_ms(1);
|
||||
}while(1);
|
||||
}
|
||||
|
||||
int main( void )
|
||||
{
|
||||
DDRC |= (1 << PC0);
|
||||
|
||||
while(1) {
|
||||
PORTC ^= (1 << PC0);
|
||||
_delay_ms(1000);
|
||||
}
|
||||
return 0;
|
||||
}
|
83
sketches/led-driver/led-driver.hex
Normal file
83
sketches/led-driver/led-driver.hex
Normal file
@ -0,0 +1,83 @@
|
||||
:100000000C9434000C943E000C943E000C943E0082
|
||||
:100010000C943E000C943E000C943E000C943E0068
|
||||
:100020000C943E000C943E000C943E000C943E0058
|
||||
:100030000C943E000C943E000C943E000C943E0048
|
||||
:100040000C943E000C943E000C943E000C943E0038
|
||||
:100050000C943E000C943E000C943E000C943E0028
|
||||
:100060000C943E000C943E0011241FBECFEFD8E04C
|
||||
:10007000DEBFCDBF0E9479020C9488020C94000070
|
||||
:1000800081E084B985B90000000000000000000094
|
||||
:10009000000015B800000000000000000000000093
|
||||
:1000A0000000000000000000000000000000000050
|
||||
:1000B000000085B900000000000000000000000002
|
||||
:1000C00015B8000000000000000000000000000063
|
||||
:1000D0000000000000000000000000000000000020
|
||||
:1000E00085B900000000000000000000000015B805
|
||||
:1000F0000000000000000000000000000000000000
|
||||
:10010000000000000000000000000000000085B9B1
|
||||
:1001100000000000000000000000000015B8000012
|
||||
:1001200000000000000000000000000000000000CF
|
||||
:1001300000000000000000000000000085B9000081
|
||||
:100140000000000000000000000015B800000000E2
|
||||
:10015000000000000000000000000000000000009F
|
||||
:100160000000000000000000000085B90000000051
|
||||
:10017000000000000000000015B8000000000000B2
|
||||
:10018000000000000000000000000000000000006F
|
||||
:10019000000000000000000085B900000000000021
|
||||
:1001A00000000000000015B8000000000000000082
|
||||
:1001B000000000000000000000000000000000003F
|
||||
:1001C00000000000000085B90000000000000000F1
|
||||
:1001D0000000000015B80000000000000000000052
|
||||
:1001E000000000000000000000000000000000000F
|
||||
:1001F0000000000085B900000000000000000000C1
|
||||
:10020000000015B800000000000000000000000021
|
||||
:1002100000000000000000000000000000000000DE
|
||||
:10022000000085B900000000000000000000000090
|
||||
:1002300015B80000000000000000000000000000F1
|
||||
:1002400000000000000000000000000000000000AE
|
||||
:1002500085B900000000000000000000000015B893
|
||||
:10026000000000000000000000000000000000008E
|
||||
:10027000000000000000000000000000000085B940
|
||||
:1002800000000000000000000000000015B80000A1
|
||||
:10029000000000000000000000000000000000005E
|
||||
:1002A00000000000000000000000000085B9000010
|
||||
:1002B0000000000000000000000015B80000000071
|
||||
:1002C000000000000000000000000000000000002E
|
||||
:1002D0000000000000000000000085B900000000E0
|
||||
:1002E000000000000000000015B800000000000041
|
||||
:1002F00000000000000000000000000000000000FE
|
||||
:10030000000000000000000085B9000000000000AF
|
||||
:1003100000000000000015B8000000000000000010
|
||||
:1003200000000000000000000000000000000000CD
|
||||
:1003300000000000000085B900000000000000007F
|
||||
:100340000000000015B800000000000000000000E0
|
||||
:10035000000000000000000000000000000000009D
|
||||
:100360000000000085B9000000000000000000004F
|
||||
:10037000000000000000000000000000000000007D
|
||||
:10038000000015B8000000000000000000000000A0
|
||||
:100390000000000085B9000000000000000000001F
|
||||
:1003A000000000000000000000000000000000004D
|
||||
:1003B000000015B800000000000000000000000070
|
||||
:1003C0000000000085B900000000000000000000EF
|
||||
:1003D000000000000000000000000000000000001D
|
||||
:1003E000000015B800000000000000000000000040
|
||||
:1003F0000000000085B900000000000000000000BF
|
||||
:1004000000000000000000000000000000000000EC
|
||||
:10041000000015B80000000000000000000000000F
|
||||
:100420000000000085B9000000000000000000008E
|
||||
:1004300000000000000000000000000000000000BC
|
||||
:10044000000015B8000000000000000000000000DF
|
||||
:100450000000000085B9000000000000000000005E
|
||||
:10046000000000000000000000000000000000008C
|
||||
:10047000000015B8000000000000000000000000AF
|
||||
:100480000000000085B9000000000000000000002E
|
||||
:10049000000000000000000000000000000000005C
|
||||
:1004A000000015B80000000000000000000000007F
|
||||
:1004B0000000000085B900000000000000000000FE
|
||||
:1004C000000000000000000000000000000000002C
|
||||
:1004D000000015B80000000000000000000000004F
|
||||
:1004E00000000000E9EFF0E03197F1F700C00000F4
|
||||
:1004F000C9CD389A91E088B1892788B92FE33DE0CA
|
||||
:1005000083E0215030408040E1F700C00000F3CF8D
|
||||
:04051000F894FFCF8D
|
||||
:00000001FF
|
BIN
sketches/led-driver/led-driver.o
Executable file
BIN
sketches/led-driver/led-driver.o
Executable file
Binary file not shown.
Reference in New Issue
Block a user