Added V2Protocol handlers to the AVRISP project to enter/exit programming mode, and read/write fuses, lockbits, OSCCAL and Signature bytes.

Added ShutDown functions for all hardware peripheral drivers, so that peripherals can be turned off after use.
Dean Camera 16 years ago
parent d540276b44
commit 1e8df8951a
  1. 6
      LUFA/Drivers/Peripheral/AT90USBXXX67/ADC.h
  2. 10
      LUFA/Drivers/Peripheral/SPI.h
  3. 13
      LUFA/Drivers/Peripheral/Serial.h
  4. 8
      LUFA/Drivers/Peripheral/SerialStream.h
  5. 1
      LUFA/ManPages/ChangeLog.txt
  6. 4
      LUFA/ManPages/MigrationInformation.txt
  7. 1
      Projects/Incomplete/AVRISP/AVRISP.c
  8. 277
      Projects/Incomplete/AVRISP/Lib/V2Protocol.c
  9. 26
      Projects/Incomplete/AVRISP/Lib/V2Protocol.h
  10. 2
      Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c

@ -118,11 +118,11 @@
* \param[in] Mode Mask of ADC settings, including adjustment, prescale, mode and reference
*/
static inline void ADC_Init(uint8_t Mode);
/** Turns off the ADC. If this is called, any further ADC operations will require a call to
* \ref ADC_Init() before the ADC can be used again.
*/
static inline void ADC_Off(void);
static inline void ADC_ShutDown(void);
/** Indicates if the ADC is currently enabled.
*
@ -145,7 +145,7 @@
#else
#define ADC_Init(mode) MACROS{ ADCSRA = ((1 << ADEN) | mode); }MACROE
#define ADC_Off() MACROS{ ADCSRA = 0; }MACROE
#define ADC_ShutDown() MACROS{ ADCSRA = 0; }MACROE
#define ADC_GetStatus() ((ADCSRA & (1 << ADEN)) ? true : false)

@ -108,6 +108,16 @@
SPSR &= ~(1 << SPI2X);
}
/** Turns off the SPI driver, disabling and returning used hardware to their default configuration. */
static inline void SPI_ShutDown(void)
{
DDRB &= ~((1 << 1) | (1 << 2));
PORTB &= ~((1 << 0) | (1 << 3));
SPCR = 0;
SPSR = 0;
}
/** Sends and receives a byte through the SPI interface, blocking until the transfer is complete.
*
* \param[in] Byte Byte to send through the SPI interface

@ -118,6 +118,19 @@
UBRR1 = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));
}
/** Turns off the USART driver, disabling and returning used hardware to their default configuration. */
static inline void Serial_ShutDown(void)
{
UCSR1A = 0;
UCSR1B = 0;
UCSR1C = 0;
DDRD &= ~(1 << 3);
PORTD &= ~(1 << 2);
UBRR1 = 0;
}
/** Transmits a given byte through the USART.
*
* \param[in] DataByte Byte to transmit through the USART

@ -88,6 +88,14 @@
stdout = &USARTStream;
}
/** Turns off the serial stream (and regular USART driver), disabling and returning used hardware to
* their default configuration.
*/
static inline void SerialStream_ShutDown(void)
{
Serial_ShutDown();
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)

@ -15,6 +15,7 @@
* USB_Device_DisableSOFEvents() macros to give bus-synchronised millisecond interrupts when in USB device mode
* - Added new Endpoint_SetEndpointDirection() macro for bi-directional endpoints
* - Added new AVRISP project, a LUFA clone of the Atmel AVRISP-MKII programmer
* - Added ShutDown functions for all hardware peripheral drivers, so that peripherals can be turned off after use
*
* <b>Changed:</b>
* - SetIdle requests to the HID device driver with a 0 idle period (send changes only) now only affect the requested

@ -11,7 +11,9 @@
* areas relevant to making older projects compatible with the API changes of each new release.
*
* \section Sec_MigrationXXXXXX Migrating from 090810 to XXXXXX
* No migration information for this version yet.
*
* <b>Non-USB Library Components</b>
* - The ADC_Off() function has been renamed to \ref ADC_ShutDown() to be consistent with the rest of the library.
*
* \section Sec_Migration090810 Migrating from 090605 to 090810
*

@ -69,7 +69,6 @@ void SetupHardware(void)
/* Hardware Initialization */
SerialStream_Init(9600, false);
SPI_Init(0, true);
LEDs_Init();
USB_Init();
}

@ -40,7 +40,7 @@ uint32_t CurrentAddress;
/* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
static const uint8_t SPIMaskFromSCKDuration[MAX_SPI_SETTINGS] =
static const uint8_t SPIMaskFromSCKDuration[] =
{
#if (F_CPU == 8000000)
SPI_SPEED_FCPU_DIV_2,
@ -52,14 +52,14 @@ static const uint8_t SPIMaskFromSCKDuration[MAX_SPI_SETTINGS] =
#endif
};
static void V2Protocol_ReconfigureSPI(void)
static uint8_t V2Protocol_GetSPIPrescalerMask(void)
{
uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
if (SCKDuration >= MAX_SPI_SETTINGS)
SCKDuration = (MAX_SPI_SETTINGS - 1);
if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);
return SPIMaskFromSCKDuration[SCKDuration];
}
static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
@ -77,6 +77,35 @@ static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
RESET_LINE_DDR &= ~RESET_LINE_MASK;
}
}
static void V2Protocol_DelayMS(uint8_t MS)
{
while (MS--)
_delay_ms(1);
}
static uint8_t V2Protocol_WaitWhileTargetBusy(void)
{
uint8_t TimeoutMS = TARGET_BUST_TIMEOUT_MS;
uint8_t ResponseByte;
do
{
V2Protocol_DelayMS(1);
SPI_SendByte(0xF0);
SPI_SendByte(0x00);
SPI_SendByte(0x00);
ResponseByte = SPI_ReceiveByte();
}
while ((ResponseByte & 0x01) && (TimeoutMS--));
if (!(TimeoutMS))
return STATUS_CMD_TOUT;
else
return STATUS_CMD_OK;
}
void V2Protocol_ProcessCommand(void)
{
@ -94,9 +123,28 @@ void V2Protocol_ProcessCommand(void)
case CMD_LOAD_ADDRESS:
V2Protocol_Command_LoadAddress();
break;
case CMD_ENTER_PROGMODE_ISP:
V2Protocol_Command_EnterISPMode();
break;
case CMD_LEAVE_PROGMODE_ISP:
V2Protocol_Command_LeaveISPMode();
break;
case CMD_CHIP_ERASE_ISP:
V2Protocol_Command_ChipErase();
break;
case CMD_READ_FUSE_ISP:
case CMD_READ_LOCK_ISP:
case CMD_READ_SIGNATURE_ISP:
case CMD_READ_OSCCAL_ISP:
V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command);
break;
case CMD_PROGRAM_FUSE_ISP:
case CMD_PROGRAM_LOCK_ISP:
V2Protocol_Command_WriteFuseLock(V2Command);
break;
case CMD_SPI_MULTI:
V2Protocol_Command_SPIMulti();
break;
break;
default:
V2Protocol_Command_Unknown(V2Command);
break;
@ -132,38 +180,40 @@ static void V2Protocol_Command_SignOn(void)
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
V2Protocol_ReconfigureSPI();
CurrentAddress = 0;
Endpoint_Write_Byte(CMD_SIGN_ON);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(PROGRAMMER_ID_LEN);
Endpoint_Write_Stream_LE(PROGRAMMER_ID, PROGRAMMER_ID_LEN);
Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);
Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));
Endpoint_ClearIN();
}
static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
{
uint8_t ParamID = Endpoint_Read_Byte();
uint8_t ParamValue = Endpoint_Read_Byte();
struct
{
uint8_t ParamID;
uint8_t ParamValue;
} Get_Set_Param_Params;
Endpoint_Read_Stream_LE(&Get_Set_Param_Params, sizeof(Get_Set_Param_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
uint8_t ParamPrivs = V2Params_GetParameterPrivellages(ParamID);
uint8_t ParamPrivs = V2Params_GetParameterPrivellages(Get_Set_Param_Params.ParamID);
Endpoint_Write_Byte(V2Command);
if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
{
Endpoint_Write_Byte(STATUS_CMD_OK);
V2Params_SetParameterValue(ParamID, ParamValue);
V2Params_SetParameterValue(Get_Set_Param_Params.ParamID, Get_Set_Param_Params.ParamValue);
}
else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
{
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));
Endpoint_Write_Byte(V2Params_GetParameterValue(Get_Set_Param_Params.ParamID));
}
else
{
@ -175,25 +225,194 @@ static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
static void V2Protocol_Command_LoadAddress(void)
{
CurrentAddress = Endpoint_Read_DWord_LE();
Endpoint_Read_Stream_LE(&CurrentAddress, sizeof(CurrentAddress));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
// TODO: Check for extended address
Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
static void V2Protocol_Command_EnterISPMode(void)
{
struct
{
uint8_t TimeoutMS;
uint8_t PinStabDelayMS;
uint8_t ExecutionDelayMS;
uint8_t SynchLoops;
uint8_t ByteDelay;
uint8_t PollValue;
uint8_t PollIndex;
uint8_t EnterProgBytes[4];
} Enter_ISP_Params;
Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
uint8_t ResponseStatus = STATUS_CMD_FAILED;
Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ExecutionDelayMS +
Enter_ISP_Params.PinStabDelayMS;
CurrentAddress = 0;
if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
V2Protocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);
V2Protocol_ChangeTargetResetLine(true);
V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
{
uint8_t ResponseBytes[4];
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
{
ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
if (Enter_ISP_Params.TimeoutMS >= Enter_ISP_Params.ByteDelay)
Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ByteDelay;
else
ResponseStatus = STATUS_CMD_TOUT;
}
if (ResponseBytes[Enter_ISP_Params.PollIndex] == Enter_ISP_Params.PollValue)
ResponseStatus = STATUS_CMD_OK;
}
Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
Endpoint_Write_Byte(ResponseStatus);
Endpoint_ClearIN();
}
static void V2Protocol_Command_LeaveISPMode(void)
{
struct
{
uint8_t PreDelayMS;
uint8_t PostDelayMS;
} Leave_ISP_Params;
Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
V2Protocol_ChangeTargetResetLine(false);
SPI_ShutDown();
V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);
Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
static void V2Protocol_Command_ChipErase(void)
{
struct
{
uint8_t EraseDelayMS;
uint8_t PollMethod;
uint8_t EraseCommandBytes[4];
} Erase_Chip_Params;
Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
uint8_t ResponseStatus = STATUS_CMD_OK;
for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
if (Erase_Chip_Params.PollMethod == 0)
V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
else
ResponseStatus = V2Protocol_WaitWhileTargetBusy();
Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
Endpoint_Write_Byte(ResponseStatus);
Endpoint_ClearIN();
}
static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
{
struct
{
uint8_t RetByte;
uint8_t ReadCommandBytes[4];
} Read_FuseLockSigOSCCAL_Params;
Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
uint8_t ResponseBytes[4];
for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte]);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
{
struct
{
uint8_t WriteCommandBytes[4];
} Write_FuseLockSig_Params;
Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
Endpoint_WaitUntilReady();
for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
}
static void V2Protocol_Command_SPIMulti(void)
{
uint8_t TxBytes = Endpoint_Read_Byte();
uint8_t RxBytes = Endpoint_Read_Byte();
uint8_t RxStartAddr = Endpoint_Read_Byte();
uint8_t TxData[255];
struct
{
uint8_t TxBytes;
uint8_t RxBytes;
uint8_t RxStartAddr;
uint8_t TxData[255];
} SPI_Multi_Params;
Endpoint_Read_Stream_LE(TxData, TxBytes);
Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) -
sizeof(SPI_Multi_Params.TxData));
Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
@ -206,10 +425,10 @@ static void V2Protocol_Command_SPIMulti(void)
uint8_t CurrRxPos = 0;
/* Write out bytes to transmit until the start of the bytes to receive is met */
while (CurrTxPos < RxStartAddr)
while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
{
if (CurrTxPos < TxBytes)
SPI_SendByte(TxData[CurrTxPos]);
if (CurrTxPos < SPI_Multi_Params.TxBytes)
SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
else
SPI_SendByte(0);
@ -217,10 +436,10 @@ static void V2Protocol_Command_SPIMulti(void)
}
/* Transmit remaining bytes with padding as needed, read in response bytes */
while (CurrRxPos < RxBytes)
while (CurrRxPos < SPI_Multi_Params.RxBytes)
{
if (CurrTxPos < TxBytes)
Endpoint_Write_Byte(SPI_TransferByte(TxData[CurrTxPos++]));
if (CurrTxPos < SPI_Multi_Params.TxBytes)
Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
else
Endpoint_Write_Byte(SPI_ReceiveByte());
@ -228,5 +447,5 @@ static void V2Protocol_Command_SPIMulti(void)
}
Endpoint_Write_Byte(STATUS_CMD_OK);
Endpoint_ClearIN();
Endpoint_ClearIN();
}

@ -38,6 +38,7 @@
/* Includes: */
#include <avr/io.h>
#include <util/delay.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Peripheral/SPI.h>
@ -47,23 +48,28 @@
#include "V2ProtocolParams.h"
/* Macros: */
#define PROGRAMMER_ID "AVRISP_MK2"
#define PROGRAMMER_ID_LEN (sizeof(PROGRAMMER_ID) - 1)
#define MAX_SPI_SETTINGS 7
#define PROGRAMMER_ID "AVRISP_MK2"
#define TARGET_BUST_TIMEOUT_MS 100
/* Function Prototypes: */
void V2Protocol_ProcessCommand(void);
#if defined(INCLUDE_FROM_V2PROTOCOL_C)
static void V2Protocol_ReconfigureSPI(void);
static uint8_t V2Protocol_GetSPIPrescalerMask(void);
static void V2Protocol_ChangeTargetResetLine(bool ResetTarget);
static void V2Protocol_DelayMS(uint8_t MS);
static uint8_t V2Protocol_WaitWhileTargetBusy(void);
static void V2Protocol_Command_Unknown(uint8_t V2Command);
static void V2Protocol_Command_SignOn(void);
static void V2Protocol_Command_GetSetParam(uint8_t V2Command);
static void V2Protocol_Command_LoadAddress(void);
static void V2Protocol_Command_SPIMulti(void);
static void V2Protocol_Command_Unknown(uint8_t V2Command);
static void V2Protocol_Command_SignOn(void);
static void V2Protocol_Command_GetSetParam(uint8_t V2Command);
static void V2Protocol_Command_LoadAddress(void);
static void V2Protocol_Command_EnterISPMode(void);
static void V2Protocol_Command_LeaveISPMode(void);
static void V2Protocol_Command_ChipErase(void);
static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command);
static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command);
static void V2Protocol_Command_SPIMulti(void);
#endif
#endif

@ -67,7 +67,7 @@ static ParameterItem_t ParameterTable[] =
.ParamPrivellages = PARAM_PRIV_READ },
{ .ParamID = PARAM_SCK_DURATION,
.ParamValue = MAX_SPI_SETTINGS,
.ParamValue = 0,
.ParamPrivellages = PARAM_PRIV_READ | PARAM_PRIV_WRITE },
{ .ParamID = PARAM_RESET_POLARITY,

Loading…
Cancel
Save