⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stk500protocol.c

📁 可用来自做的AVR-USB-ISP的源码,内符电路图,用AVR M8来模拟USB接口
💻 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 + -