avrgirl flavoured stk500v2 protocol communication for compatible programming devices.
npm install avrgirl-stk500v2
avrgirl-stk500v2 is a NodeJS implementation of the stk500v2 protocol. It facilitates the 2-way communication required to program and read supported Atmel AVR microchips and programmers alike.
Current feature implementation of avrgirl-stk500v2:
- Enter / leave programming mode
- Read programmer/chip signatures
- Write to EEPROM and Flash memory
- Read from EEPROM and Flash memory
- Erase chip memory
- Read and write fuses
- Get and set parameters
- Support for both libusb and serialport connections
Let's say you'd like to use NodeJS to flash and erase microchips. This could be an Arduino Mega, or an integrated circuit with an embedded AVR microchip. For example, you could flash a precompiled program to the following setup with an STK500v2 compatible programmer, such as an AVRISP mkII:
Your approach here will vary with what you're connecting to. The two NodeJS USB packages that this library supports are usb and serialport. Choose the one that will work with your STK500v2 device.
avrgirl-stk500v2 needs some input from you when instantiating. This is because we don't know which chip you would like to flash yet, which usb method you're using, or which variety of STK500v2 you require (framed or frameless).
The options needed have the following signature:
var options = {
comm: [Object],
chip: [Object],
frameless: [Boolean],
debug: [Boolean]
};
Confused? Let's have a look at each one.
options.comm
This is the communication method required. Pass in an established instance of either serialport or usb. See the examples in how to use.
options.chip
The chip property is an object that follows a strict format / signature. It specifies the configuration properties of the microchip you are using. You'll need to know and supply this configuration. You can find this from AVR Studio, the avrgirl-chips-json package, or use the AVRDUDE conf API. Pull requests to the avrgirl-chips-json repo with additional chips is most welcome.
Here is the signature, provided as an example of the ATtiny85:
{
"name": "ATtiny85",
"timeout": 200,
"stabDelay": 100,
"cmdexeDelay": 25,
"syncLoops": 32,
"byteDelay": 0,
"pollIndex": 3,
"pollValue": 83,
"preDelay": 1,
"postDelay": 1,
"pgmEnable": [172, 83, 0, 0],
"erase": {
"cmd": [172, 128, 0, 0],
"delay": 45,
"pollMethod": 1
},
"flash": {
"write": [64, 76, 0],
"read": [32, 0, 0],
"mode": 65,
"blockSize": 64,
"delay": 10,
"poll2": 255,
"poll1": 255,
"size": 8192,
"pageSize": 64,
"pages": 128,
"addressOffset": 0
},
"eeprom": {
"write": [193, 194, 0],
"read": [160, 0, 0],
"mode": 65,
"blockSize": 4,
"delay": 5,
"poll2": 255,
"poll1": 255,
"size": 512,
"pageSize": 4,
"pages": 128,
"addressOffset": 0
},
"sig": [30, 147, 11],
"signature": {
"size": 3,
"startAddress": 0,
"read": [48, 0, 0, 0]
},
"fuses": {
"startAddress": 0,
"write": {
"low": [172, 160, 0, 0],
"high": [172, 168, 0, 0],
"ext": [172, 164, 0, 0]
},
"read": {
"low": [80, 0, 0, 0],
"high": [88, 8, 0, 0],
"ext": [80, 8, 0, 0]
}
}
}
options.frameless
Defaults to false
if this property is not specified.
Some STK500v2 devices use frameless messaging mode, and some use framed. What is the difference? See below:
Framed Format |
---|
MESSAGE START |
SEQUENCE NUMBER |
MESSAGE LENGTH |
TOKEN |
MESSAGE BODY |
CHECKSUM |
or
Frameless Format |
---|
MESSAGE BODY |
Read the manual for the device being used in order to find which messaging mode is needed.
options.debug
Defaults to false
if this property is not specified.
Logs activity information to the console while performing methods.
var stk500v2 = require('avrgirl-stk500v2');
var Serialport = require('serialport');
var sp = new Serialport('/dev/cu.usbmodem1411', {
baudRate: 115200,
parser: Serialport.parsers.raw,
autoOpen: false
});
var mega = {
// all chip properties
};
var options = {
comm: sp,
chip: mega,
frameless: false
}
var stk = new stk500v2(options);
stk.on('ready', function() {
// do cool chip stuff in here
});
var stk500v2 = require('avrgirl-stk500v2');
var usb = require('usb');
var attiny45 = {
// all chip properties
};
var programmer = usb.findByIds(0x03eb, 0x2104);
var options = {
comm: programmer,
chip: attiny45,
frameless: true
}
var stk = new stk500v2(options);
stk.on('ready', function() {
// do cool chip stuff in here
});
This is a convenient, fast way to write to the flash memory of the microchip.
Underneath, this method is doing the following:
- Enters programming mode
- Calls writeFlash and writes to the flash memory on the chip
- Exits programming mode and calls back
It does not erase the chip before writing.
Provide a filepath string, and a callback, respectively. Alternatively, you may also provide a pre-parsed Buffer in in place of the filepath.
Returns a null error upon callback if successful.
stk.quickFlash('Blink.cpp.hex', function(error) {
console.log(error);
});
This is a convenient, fast way to write to the eeprom memory of the microchip.
Underneath, this method is doing the following:
- Enters programming mode
- Calls writeEeprom and writes to the eeprom memory on the chip
- Exits programming mode and calls back
It does not erase the chip before writing.
Provide a filepath string, and a callback, respectively. Alternatively, you may also provide a pre-parsed Buffer in in place of the filepath.
Returns a null error upon callback if successful.
stk.quickEeprom('myEeprom.cpp.hex', function(error) {
console.log(error);
});
Gets the signature of the microchip.
Returns a buffer containing the signature bytes.
Usage:
stk.getChipSignature(function(error, signature) {
console.log(signature);
});
Gets the signature of the STK500V2 device, but not necessarily the microchip's signature. This is normally the signature of middleperson STK500v2 programmer if you're using one. To get the microchip's signature, use the getChipSignature
method instead.
Returns a buffer containing the signature bytes.
Usage:
stk.getSignature(function(error, signature) {
console.log(signature);
});
Enables programming mode on the microchip.
Returns a null error upon callback if successful.
stk.enterProgrammingMode(function(error) {
console.log(error);
});
Leaves programming mode on the microchip. Returns a null error upon callback if successful.
stk.exitProgrammingMode(function(error) {
console.log(error);
});
Erases both the flash and EEPROM memories on the microchip. Good practice to do before flashing any new data.
💣💣💣 Literally erases everything please be careful 💣💣💣
Returns a null error upon callback if successful.
stk.eraseChip(function(error) {
console.log(error);
});
Gets the value of a specified parameter. Pass in the parameter's byte label and a callback respectively.
Returns a null error and the parameter value upon callback if successful.
stk.getParameter(0x94, function(error, data) {
console.log(error, data);
});
Sets the value of a specified parameter. Pass in the parameter's byte label, the requested value, and a callback respectively.
Returns a null error upon callback if successful.
stk.setParameter(0x94, 0x00, function(error) {
console.log(error);
});
Writes a buffer to the flash memory of the microchip. Provide a filepath string, and a callback, respectively. Alternatively, you may also provide a pre-parsed Buffer in in place of the filepath.
Returns a null error upon callback if successful.
stk.writeFlash('Blink.cpp.hex', function(error) {
console.log(error);
});
Writes a buffer to the eeprom memory of the microchip. Provide a filepath string, and a callback, respectively. Alternatively, you may also provide a pre-parsed Buffer in in place of the filepath.
Returns a null error upon callback if successful.
stk.writeEeprom('myEeprom.cpp.hex', function(error) {
console.log(error);
});
Reads a specified length of flash memory from the microchip. Takes a length integer (or hex) for the number of bytes to read, and a callback as the arguments, respectively.
Returns a null error and a buffer of the read bytes upon callback if successful.
Usage:
stk.readFlash(64, function(error, data) {
console.log(data);
});
Reads a specified length of flash memory from the microchip. Takes a length integer (or hex) for the number of bytes to read, and a callback as the arguments, respectively.
Returns a null error and a buffer of the read bytes upon callback if successful.
Usage:
stk.readEeprom(64, function(error, data) {
console.log(error, data);
});
Reads all of the available fuse values on the microchip.
Returns a null error and an object containing the fuse key and byte value pairs upon callback if successful.
Usage:
stk.readFuses(function(error, data) {
console.log(error, data);
});
Reads a specific fuse on the microchip. Pass in a string of the right fuse key from the chip properties.
Returns a null error and a buffer containing the fuse byte value upon callback if successful.
Usage:
stk.readFuse('low', function(error, data) {
console.log(error, data);
});
💣💣💣 OMG, please be careful with this. 💣💣💣
please please please.
You can brick your chip if you do not know exactly what you're doing. Use an online fuse calculator first, and triple check before running this method.
I accept no responsibility for bricked chips 💀😱ðŸ˜
Takes a fuse key string, a value to set it to, and a callback.
Usage:
// *********
// please do not run this code unless you're sure that 0x62 is a good idea for your chip ;___;
// *********
stk.writeFuse('low', 0x62, function(error) {
// note: a null error doesn't necessarily mean you didn't do something foolish here.
console.log(error);
});
NOTE: The following methods below are rarely needed, but documented in case you have need for them.
Void. Upon instantiation, avrgirl-stk500v2 opens a connection to the device. You shouldn't need to call this method unless you've previously closed the connection manually.
Usage:
stk.open();
Void. Closes the connection to the STK500V2 device.
Usage:
stk.close();
Writes a buffer of data to the STK500V2 device. Takes a buffer and a callback as the arguments, respectively.
Usage:
var buffer = new Buffer([0x01, 0x00, 0x00]);
stk.write(buffer, function(error) {
console.log('written.');
});
Reads the last response from the STK500V2 device. Takes a length integer (number of bytes to read), and a callback as the arguments, respectively. Generally you'll want to call this immediately after a write.
Usage:
var buffer = new Buffer([0x01, 0x00, 0x00]);
stk.write(buffer, function(error) {
stk.read(2, function(error, data) {
console.log(data);
});
});
SendCmd is a shortcut to sending an instruction buffer, of which you're simply expecting an 'OK' back. Your instruction will be sent, and the callback will return a null error if an 'OK' response returned.
In frameless mode, the expected response needs to be 2 bytes, and in framed it should be 8. Not compatible with instructions that aren't simply a simple command for the device. Use write, or the matched method for what you're wanting to achieve.
Returns a null error if successful.
var buffer = new Buffer([0x01, 0x00, 0x00]);
stk.sendCmd(buffer, function(error) {
console.log(error);
});