X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/bbcdaaa6dc6024911a280e5fda6b4a43f71fb98e..05fcf7e2a79bebb978d4aeaef26b12f70c6826f8:/Projects/AVRISP/Lib/V2Protocol.c diff --git a/Projects/AVRISP/Lib/V2Protocol.c b/Projects/AVRISP/Lib/V2Protocol.c index 304eef471..eae2e830f 100644 --- a/Projects/AVRISP/Lib/V2Protocol.c +++ b/Projects/AVRISP/Lib/V2Protocol.c @@ -36,126 +36,191 @@ #define INCLUDE_FROM_V2PROTOCOL_C #include "V2Protocol.h" -ParameterItem_t ParameterTable[] EEMEM = - { - { .ParameterID = PARAM_BUILD_NUMBER_LOW, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_BUILD_NUMBER_HIGH, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_HW_VER, - .ParameterValue = 0x01 }, - { .ParameterID = PARAM_SW_MAJOR, - .ParameterValue = 0x01 }, - { .ParameterID = PARAM_SW_MINOR, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_VTARGET, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_SCK_DURATION, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_RESET_POLARITY, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_STATUS_TGT_CONN, - .ParameterValue = 0x00 }, - { .ParameterID = PARAM_DISCHARGEDELAY, - .ParameterValue = 0x00 }, - }; - -void V2Protocol_ProcessCommand(void) -{ - uint8_t V2Command = Endpoint_Read_Byte(); - - printf("COMMAND %d\r\n", V2Command); +/** Current memory address for FLASH/EEPROM memory read/write commands */ +uint32_t CurrentAddress; + +/** Flag to indicate that the next read/write operation must update the device's current address */ +bool MustSetAddress; + +/** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host. + * This routine decodes the issued command and passes off the handling of the command to the + * appropriate function. + */ +void V2Protocol_ProcessCommand(void) +{ + uint8_t V2Command = Endpoint_Read_Byte(); + + Serial_TxByte(V2Command); + switch (V2Command) { case CMD_SIGN_ON: - V2Protocol_ProcessCmdSignOn(); + V2Protocol_SignOn(); break; case CMD_SET_PARAMETER: - V2Protocol_ProcessCmdSetParam(); - break; case CMD_GET_PARAMETER: - V2Protocol_ProcessCmdGetParam(); + V2Protocol_GetSetParam(V2Command); + break; + case CMD_LOAD_ADDRESS: + V2Protocol_LoadAddress(); + break; + case CMD_RESET_PROTECTION: + V2Protocol_ResetProtection(); + break; +#if defined(ENABLE_ISP_PROTOCOL) + case CMD_ENTER_PROGMODE_ISP: + ISPProtocol_EnterISPMode(); + break; + case CMD_LEAVE_PROGMODE_ISP: + ISPProtocol_LeaveISPMode(); + break; + case CMD_PROGRAM_FLASH_ISP: + case CMD_PROGRAM_EEPROM_ISP: + ISPProtocol_ProgramMemory(V2Command); + break; + case CMD_READ_FLASH_ISP: + case CMD_READ_EEPROM_ISP: + ISPProtocol_ReadMemory(V2Command); + break; + case CMD_CHIP_ERASE_ISP: + ISPProtocol_ChipErase(); + break; + case CMD_READ_FUSE_ISP: + case CMD_READ_LOCK_ISP: + case CMD_READ_SIGNATURE_ISP: + case CMD_READ_OSCCAL_ISP: + ISPProtocol_ReadFuseLockSigOSCCAL(V2Command); break; + case CMD_PROGRAM_FUSE_ISP: + case CMD_PROGRAM_LOCK_ISP: + ISPProtocol_WriteFuseLock(V2Command); + break; + case CMD_SPI_MULTI: + ISPProtocol_SPIMulti(); + break; +#endif +#if defined(ENABLE_PDI_PROTOCOL) + case CMD_XPROG_SETMODE: + PDIProtocol_XPROG_SetMode(); + break; + case CMD_XPROG: + PDIProtocol_XPROG_Command(); + break; +#endif +#if defined(ENABLE_TPI_PROTOCOL) + // TODO +#endif default: - Endpoint_ClearOUT(); - Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - Endpoint_Write_Byte(STATUS_CMD_UNKNOWN); - Endpoint_ClearIN(); + V2Protocol_UnknownCommand(V2Command); break; } - /* Reset Endpoint direction to OUT ready for next command */ - Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); + Endpoint_WaitUntilReady(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT); } -static ParameterItem_t* V2Protocol_GetParameterItem(uint8_t ParamID) +/** Handler for unknown V2 protocol commands. This discards all sent data and returns a + * STATUS_CMD_UNKNOWN status back to the host. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +static void V2Protocol_UnknownCommand(const uint8_t V2Command) { - for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++) + /* Discard all incoming data */ + while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE) { - if (ParamID == eeprom_read_byte(&ParameterTable[TableIndex].ParameterID)) - return &ParameterTable[TableIndex]; + Endpoint_ClearOUT(); + Endpoint_WaitUntilReady(); } - - return NULL; -} - -static void V2Protocol_ProcessCmdSignOn(void) + + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(V2Command); + Endpoint_Write_Byte(STATUS_CMD_UNKNOWN); + Endpoint_ClearIN(); +} + +/** Handler for the CMD_SIGN_ON command, returning the programmer ID string to the host. */ +static void V2Protocol_SignOn(void) { Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - + 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_ProcessCmdSetParam(void) +/** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function + * as no ISP short-circuit protection is currently implemented. + */ +static void V2Protocol_ResetProtection(void) { - uint8_t ParamID = Endpoint_Read_Byte(); - uint8_t ParamValue = Endpoint_Read_Byte(); + Endpoint_ClearOUT(); + Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + Endpoint_Write_Byte(CMD_RESET_PROTECTION); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); +} + - ParameterItem_t* ParameterItem = V2Protocol_GetParameterItem(ParamID); +/** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or + * getting a device parameter's value from the parameter table. + * + * \param[in] V2Command Issued V2 Protocol command byte from the host + */ +static void V2Protocol_GetSetParam(const uint8_t V2Command) +{ + uint8_t ParamID = Endpoint_Read_Byte(); + uint8_t ParamValue; + if (V2Command == CMD_SET_PARAMETER) + ParamValue = Endpoint_Read_Byte(); + Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); - - if (ParameterItem != NULL) + + Endpoint_Write_Byte(V2Command); + + uint8_t ParamPrivs = V2Params_GetParameterPrivileges(ParamID); + + if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE)) { - eeprom_write_byte(&ParameterItem->ParameterValue, ParamValue); - - Endpoint_Write_Byte(CMD_SET_PARAMETER); - Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_Write_Byte(STATUS_CMD_OK); + V2Params_SetParameterValue(ParamID, ParamValue); } - else + else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ)) { + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID)); + } + else + { Endpoint_Write_Byte(STATUS_CMD_FAILED); } Endpoint_ClearIN(); } -static void V2Protocol_ProcessCmdGetParam(void) +/** Handler for the CMD_LOAD_ADDRESS command, loading the given device address into a + * global storage variable for later use, and issuing LOAD EXTENDED ADDRESS commands + * to the attached device as required. + */ +static void V2Protocol_LoadAddress(void) { - uint8_t ParamID = Endpoint_Read_Byte(); + Endpoint_Read_Stream_BE(&CurrentAddress, sizeof(CurrentAddress)); - ParameterItem_t* ParameterItem = V2Protocol_GetParameterItem(ParamID); - Endpoint_ClearOUT(); Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN); + + MustSetAddress = true; - if (ParameterItem != NULL) - { - Endpoint_Write_Byte(CMD_GET_PARAMETER); - Endpoint_Write_Byte(STATUS_CMD_OK); - Endpoint_Write_Byte(eeprom_read_byte(&ParameterItem->ParameterValue)); - } - else - { - Endpoint_Write_Byte(STATUS_CMD_FAILED); - } - - Endpoint_ClearIN(); + Endpoint_Write_Byte(CMD_LOAD_ADDRESS); + Endpoint_Write_Byte(STATUS_CMD_OK); + Endpoint_ClearIN(); }