📄 stk500protocol.c
字号:
/************************************************************************************************ * Project: USB AVR-ISP * Author: Christian Ulrich
* Contact: christian at ullihome dot de
* * Creation Date: 2007-03-22 * Copyright: (c) 2007 by Christian Ulrich * License: GPLv2 ***********************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include "stk500protocol.h"
#include "usb_uart.h"
#include "isp.h"
#include "timer.h"
#include "led.h"
#include "main.h"
#include <util/delay.h>
#define BUFFER_SIZE 281 /* results in 275 bytes max body size */#define RX_TIMEOUT 200 /* timeout in milliseconds */#define STK_TXMSG_START 5static uint8_t Buffer[BUFFER_SIZE];static uint16_t rxPos;
static uint16_t rxLen;static uint16_t txLen;
uint8_t STK500_Status;
stkParam_t STK500_Param;
uint32_t STK500_Address;
uint8_t eeSoftwareMajor EEMEM;
uint8_t eeSoftwareMinor EEMEM;
void STK500_init()
{
STK500_Status = PGM_STATUS_IDLE;
STK500_Param.s.softwareVersionMajor = eeprom_read_byte(&eeSoftwareMajor);
STK500_Param.s.softwareVersionMinor = eeprom_read_byte(&eeSoftwareMinor);
if (STK500_Param.s.softwareVersionMajor > 0xa)
{
STK500_Param.s.softwareVersionMajor = 2;
STK500_Param.s.softwareVersionMinor = 0xa;
}
STK500_Param.s.hardwareVersion = 1;
}
void STK500_save()
{
eeprom_write_byte(&eeSoftwareMajor,STK500_Param.s.softwareVersionMajor);
eeprom_write_byte(&eeSoftwareMinor,STK500_Param.s.softwareVersionMinor);
}
void STK500_sendmessage()
{
uint8_t *p = Buffer, sum = 0;
uint16_t len; *p++ = STK_STX; *p++ = Buffer[1]; /* sequence number */ *p++ = txLen >> 8; *p++ = txLen; *p++ = STK_TOKEN;
len = txLen+6; txLen = len--; p = Buffer; while(len--)
sum ^= *p++; *p = sum;
p = Buffer;
while (txLen--)
UART_putc(*p++);}
void STK500_processmessage()
{
txLen = 2;
uint16_t i;
uint8_t res = 0;
uint8_t Address_as_byte = 0;
uint16_t len;
uint8_t tmp;
switch (Buffer[STK_TXMSG_START])
{
case STK_CMD_SIGN_ON:
{
static PROGMEM uint8_t STK500_initstring[] = {8, 'S', 'T', 'K', '5', '0', '0', '_', '2', 0}; uint8_t *p = &Buffer[STK_TXMSG_START + 2]; strcpy_P(p, STK500_initstring); Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK; txLen = 11;
break;
}
case STK_CMD_SET_PARAMETER:
{ STK500_Param.bytes[Buffer[STK_TXMSG_START + 1] & 0x1f] = Buffer[STK_TXMSG_START + 2]; if (Buffer[STK_TXMSG_START + 1] == STK_PARAM_SCK_DURATION)
{ switch (Buffer[STK_TXMSG_START + 2])
{
case 0xfe:
case 0x4c:
case 0x3:ISP_Speed = 1;break;
case 0x2:ISP_Speed = 2;break;
case 0x1:ISP_Speed = 4;break;
case 0x0:ISP_Speed = 6;
}
}
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK; break;
}
case STK_CMD_GET_PARAMETER:
{
if (Buffer[STK_TXMSG_START + 1] == STK_PARAM_SCK_DURATION)
{ switch (ISP_Speed)
{
case 1:STK500_Param.s.sckDuration = 0xfe;break;
case 2:
case 3:STK500_Param.s.sckDuration = 0x2;break;
case 4:
case 5:STK500_Param.s.sckDuration = 0x1;break;
case 6:
case 7:STK500_Param.s.sckDuration = 0x0;
}
}
else if (Buffer[STK_TXMSG_START + 1] == STK_PARAM_VTARGET)
{
#if defined(USBASP_COMPATIBLE)||defined(CCCB_COMPATIBLE)
STK500_Param.s.vTarget = 50;
#else
STK500_Param.s.vTarget = ISP_getsupplyvoltage();
#endif
}
Buffer[STK_TXMSG_START + 2] = STK500_Param.bytes[Buffer[STK_TXMSG_START + 1] & 0x1f]; Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK; txLen = 3;
break;
}
case STK_CMD_ENTER_PROGMODE_ISP:
{
if (PGM_statuschanged != NULL)
PGM_statuschanged(PGM_STATUS_PROGRAMMING);
STK500_Status = PGM_STATUS_PROGRAMMING;
ISP_connect();
if (ISP_enterprogrammingmode() == 0)
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
else
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_FAILED;
break;
}
case STK_CMD_LEAVE_PROGMODE_ISP:
{
ISP_disconnect();
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
if (PGM_statuschanged != NULL)
PGM_statuschanged(PGM_STATUS_IDLE);
STK500_Status = PGM_STATUS_IDLE;
break;
}
case STK_CMD_CHIP_ERASE_ISP:
{
ISP_erase();
TIMER_delay(((stkChipEraseIsp_t*) &Buffer[STK_TXMSG_START + 1])->eraseDelay);
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
break;
}
case STK_CMD_READ_FUSE_ISP:
case STK_CMD_READ_LOCK_ISP:
case STK_CMD_READ_SIGNATURE_ISP:
case STK_CMD_READ_OSCCAL_ISP:
{
for (i=0;i<4;i++)
if (i == ((stkReadFuseIsp_t*) &Buffer[STK_TXMSG_START + 1])->retAddr-1)
res = ISP_transmit(((stkReadFuseIsp_t*) &Buffer[STK_TXMSG_START + 1])->cmd[i]);
else
ISP_transmit(((stkReadFuseIsp_t*) &Buffer[STK_TXMSG_START + 1])->cmd[i]);
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
Buffer[STK_TXMSG_START + 2] = res;
Buffer[STK_TXMSG_START + 3] = STK_STATUS_CMD_OK;
txLen = 4; break;
}
case STK_CMD_PROGRAM_LOCK_ISP:
case STK_CMD_PROGRAM_FUSE_ISP:
{
for (i=0;i<4;i++)
ISP_transmit(((stkProgramFuseIsp_t*) &Buffer[STK_TXMSG_START + 1])->cmd[i]);
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
Buffer[STK_TXMSG_START + 2] = STK_STATUS_CMD_OK;
txLen = 3;
break; }
case STK_CMD_LOAD_ADDRESS:
{
STK500_Address = Buffer[STK_TXMSG_START + 1];
STK500_Address = (STK500_Address << 8)|Buffer[STK_TXMSG_START + 2];
STK500_Address = (STK500_Address << 8)|Buffer[STK_TXMSG_START + 3];
STK500_Address = (STK500_Address << 8)|Buffer[STK_TXMSG_START + 4];
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
break; }
case STK_CMD_PROGRAM_EEPROM_ISP:
Address_as_byte = 1;
case STK_CMD_PROGRAM_FLASH_ISP:
{
#define progFlashParam ((stkProgramFlashIsp_t*) &Buffer[STK_TXMSG_START + 1])
uint8_t valuePollingMask, rdyPollingMask;
uint8_t pollmode;
uint16_t startaddress = STK500_Address;
res = STK_STATUS_CMD_OK;
len= ((int)progFlashParam->numBytes[0])<<8; len|= progFlashParam->numBytes[1];
for (i=0;i<len;i++)
{
if ((i&8)==8)
usbPoll();
if (!Address_as_byte)
ISP_transmit(progFlashParam->cmd[0] | ((i & 1) << 3));
else ISP_transmit(progFlashParam->cmd[0]);
ISP_transmit(STK500_Address>>8); ISP_transmit(STK500_Address);
ISP_transmit(progFlashParam->data[i]);
if (!Address_as_byte)
{
if (i&1)
STK500_Address++;
}
else
STK500_Address++;
if (progFlashParam->mode & 1) //page mode
{
if ((i < len-1) || !(progFlashParam->mode & 0x80)) continue;
//write page
ISP_transmit(progFlashParam->cmd[1]);
ISP_transmit(startaddress >> 8); ISP_transmit(startaddress); ISP_transmit(0); valuePollingMask = 0x20; rdyPollingMask = 0x40;
}
else //word mode
{
valuePollingMask = 4; rdyPollingMask = 8;
}
pollmode = progFlashParam->mode;
if (progFlashParam->poll[0] == progFlashParam->data[i])
pollmode = 0;
//poll
/* if (pollmode & valuePollingMask)
{ //value polling
// TIMER_start(progFlashParam->delay); tmp = progFlashParam->poll[0];
while (tmp == progFlashParam->poll[0])
{
if (!Address_as_byte)
ISP_transmit(progFlashParam->cmd[2] | ((i & 1) << 3));
else ISP_transmit(progFlashParam->cmd[2]);
ISP_transmit(STK500_Address >> 8); ISP_transmit(STK500_Address);
tmp = ISP_transmit(0);
tmp = 0;
if(TIMER_overflowed())
{ res = STK_STATUS_CMD_TOUT;
break;
} }
}
else */if (pollmode & rdyPollingMask)
{ //ready polling
TIMER_start((progFlashParam->delay)); while(ISP_deviceisbusy())
{
// usbPoll();
if(TIMER_overflowed()) res = STK_STATUS_RDY_BSY_TOUT;
} res = STK_STATUS_CMD_OK; }
else
{ //timed polling
TIMER_start(progFlashParam->delay);
while (TIMER_timeout)
usbPoll(); res = STK_STATUS_CMD_OK;
}
}
Buffer[STK_TXMSG_START + 1] = res;
break;
}
case STK_CMD_READ_EEPROM_ISP:
Address_as_byte = 1;
case STK_CMD_READ_FLASH_ISP:
{
len = (((stkReadFlashIsp_t*) &Buffer[STK_TXMSG_START + 1])->numBytes[0]<<8)+((stkReadFlashIsp_t*) &Buffer[STK_TXMSG_START + 1])->numBytes[1];
tmp = ((stkReadFlashIsp_t*) &Buffer[STK_TXMSG_START + 1])->cmd;
for (i=0;i<len;i++)
{
MAIN_critical_tasks(); //keep main tasks alive (wdt,usb)
if (!Address_as_byte)
ISP_transmit(tmp | ((i & 1) << 3));
else ISP_transmit(tmp);
ISP_transmit(STK500_Address >> 8); ISP_transmit(STK500_Address);
Buffer[STK_TXMSG_START + 2 + i] = ISP_transmit(0);
if (!Address_as_byte)
{
if (i&1)
STK500_Address++;
}
else
STK500_Address++;
}
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
Buffer[STK_TXMSG_START + 1 + len + 1] = STK_STATUS_CMD_OK;
txLen = len+3; break;
} case STK_CMD_SPI_MULTI:
{
#define progMultiParam ((stkMultiIsp_t*) &Buffer[STK_TXMSG_START + 1])
uint8_t lentx = progMultiParam->numTx;
uint8_t lenrx = progMultiParam->numRx;
uint8_t rxstart = progMultiParam->rxStartAddr;
uint8_t rxpos = 1;
for (i = 1;i<lentx+1;i++)
{
if (i >= rxstart)
{
Buffer[STK_TXMSG_START + 1 + rxpos] = ISP_transmit(progMultiParam->txData[i]);
rxpos++;
}
else
ISP_transmit(progMultiParam->txData[i]);
}
while (rxpos < lenrx)
{
Buffer[STK_TXMSG_START + 1 + rxpos] = ISP_transmit(progMultiParam->txData[i]);
rxpos++;
}
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_OK;
Buffer[STK_TXMSG_START + 1 + lenrx + 1] = STK_STATUS_CMD_OK;
txLen = lenrx+3; break;
}
default:
{
Buffer[STK_TXMSG_START + 1] = STK_STATUS_CMD_FAILED;
}
}
STK500_sendmessage();
}
void STK500_byterecived(uint8_t data)
{
if(rxPos == 0)
{ if (data == STK_STX) Buffer[rxPos++] = data; }
else
{ if(rxPos < BUFFER_SIZE)
{ Buffer[rxPos++] = data; if (rxPos == 4)
{ rxLen = (Buffer[2] << 8)+Buffer[3]; rxLen += 6; if(rxLen > BUFFER_SIZE) //wrong length
{
rxPos = 0;
} }
else if (rxPos == 5)
{ if(data != STK_TOKEN)
{
rxPos = 0;
} }
else if (rxPos > 4 && rxPos == rxLen)
{ uint8_t sum = 0;//calculate chksum uint8_t *p = Buffer; while(rxPos)
{ sum ^= *p++; rxPos--; } if(sum == 0) //chksum ok
{
STK500_processmessage(); }
else //chksum error
{ Buffer[STK_TXMSG_START] = STK_ANSWER_CKSUM_ERROR; Buffer[STK_TXMSG_START + 1] = STK_ANSWER_CKSUM_ERROR; txLen = 3; STK500_sendmessage();
} } }
else
{
rxPos = 0; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -