From 1e8df8951a3335e4b45ad0c25a82df3d90d785f3 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Sun, 23 Aug 2009 04:01:49 +0000 Subject: 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. --- Projects/Incomplete/AVRISP/Lib/V2Protocol.c | 277 +++++++++++++++++++--- Projects/Incomplete/AVRISP/Lib/V2Protocol.h | 26 +- Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c | 2 +- 3 files changed, 265 insertions(+), 40 deletions(-) (limited to 'Projects/Incomplete/AVRISP/Lib') diff --git a/Projects/Incomplete/AVRISP/Lib/V2Protocol.c b/Projects/Incomplete/AVRISP/Lib/V2Protocol.c index e55a7002e..c31fd0eb5 100644 --- a/Projects/Incomplete/AVRISP/Lib/V2Protocol.c +++ b/Projects/Incomplete/AVRISP/Lib/V2Protocol.c @@ -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(); } diff --git a/Projects/Incomplete/AVRISP/Lib/V2Protocol.h b/Projects/Incomplete/AVRISP/Lib/V2Protocol.h index 5283f1986..116df8d89 100644 --- a/Projects/Incomplete/AVRISP/Lib/V2Protocol.h +++ b/Projects/Incomplete/AVRISP/Lib/V2Protocol.h @@ -38,6 +38,7 @@ /* Includes: */ #include + #include #include #include @@ -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 diff --git a/Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c b/Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c index 777770188..3a42ba32d 100644 --- a/Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c +++ b/Projects/Incomplete/AVRISP/Lib/V2ProtocolParams.c @@ -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, -- cgit v1.2.3