+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
- AVR ISP Programmer code Copyright 2009 Opendous Inc. (www.opendous.org)\r
- For more info and usage instructions for this firmware, visit:\r
- http://code.google.com/p/avropendous/wiki/AVR_ISP_Programmer\r
-\r
- Note that this firmware is designed to work with AVRdude:\r
- http://savannah.nongnu.org/projects/avrdude\r
- But should work with other software that supports the AVR910 ISP\r
- programmer or STK200 hardware.\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/*\r
- Usage:\r
- avrdude -vv -F -P COM7 -c avr910 -p t261\r
- Note -F flag which overrides signature check and enables programming\r
- of any "In-System Programmable via SPI Port" AVR MCU. Part number,\r
- t261, should be set to your target device.\r
- avrdude -vv -F -P COM7 -c avr910 -p t261 -U flash:w:PROG.hex\r
- PROG.hex is the hex file to program your t261 AVR with\r
- avrdude -vv -F -P COM7 -b 115200 -c avr910 -p t261 -U flash:w:test.hex\r
- The -b 115200 sets the SPI clock to 62.5kHz from the default 125kHz and may\r
- work when the default programming speed fails.\r
- AVROSP.exe -dATtiny261 -cCOM7 -rf\r
- AVRosp is the Open Source AVR ISP Programming Software available from Atmel.com\r
-\r
- Note: on Linux systems, COM7 should be replaced with someting like /dev/ttyACM0\r
- You can determine this value by running dmesg after plugging in the device\r
- Note: you must RESET the programmer after each use (AVRdude session).\r
-\r
- Note: If you experience errors with older devices, try changing the DELAY defines\r
-\r
- MISO, MOSI, and SCK are connected directly from the AVRopendous board\r
- to the pin of the same functionality on the target. RESET pin on the target\r
- can be connected either to SS (PB0), or PC2. Do not have any other pins\r
- connected - especially HWB pin, to avoid unintentional behaviour.\r
-\r
- AVR910 functionality was overlayed on USBtoSerial functionality.\r
- Keep this in mind when looking over the code.\r
- Default target speed is 125kHz and corresponds to 19200 baud, which\r
- is the default setting for AVRdude.\r
-\r
- Changing "Baud-Rate" will change the SPI speed. Defualt SPI clock speed\r
- is 8Mhz / 4 = 2MHz. 8Mhz is the device clock speed. This is the setting at\r
- 9600 baud. The following is a table of baud-rate vs. SPI Speed that will result\r
- 9600 = 2Mhz\r
- 14400 = 1MHz\r
- 19200 = 125kHz (AVRdude Default)\r
- 38400 = 250kHz\r
- 57600 = 500kHz\r
- 115200 = 62.5kHz\r
-\r
- Before running, you will need to install the INF file that\r
- is located in the project directory. This will enable\r
- Windows to use its inbuilt CDC drivers, negating the need\r
- for special Windows drivers for the device. To install,\r
- right-click the .INF file and choose the Install option.\r
-*/\r
-\r
-/* TODO: - fix the requirement that a RESET must be performed after each session, which\r
- is only an issue under Windows. Everything works fine under Linux\r
-*/\r
-\r
-#include "AVRISP_Programmer.h"\r
-\r
-/* Project Tags, for reading out using the ButtLoad project */\r
-BUTTLOADTAG(ProjName, "LUFA AVR910 ISP Programmer");\r
-BUTTLOADTAG(BuildTime, __TIME__);\r
-BUTTLOADTAG(BuildDate, __DATE__);\r
-BUTTLOADTAG(LUFAVersion, "LUFA V" LUFA_VERSION_STRING);\r
-\r
-\r
-#define RESETPORT PORTB\r
-#define RESETPIN PB0\r
-#define RESETPORT2 PORTC\r
-#define RESETPIN2 PC2\r
-#define CR_HEX '\r'\r
-\r
-#define DELAY_VERYSHORT 0x01\r
-#define DELAY_SHORT 0x02\r
-#define DELAY_MEDIUM 0x03\r
-#define DELAY_LONG 0x05\r
-#define DELAY_MULTIPLE 0x02\r
-\r
-\r
-/* AVR Device Codes - Can have a maximum of 14 but can be any you want.\r
- Note that these are completely irrelevent. If AVRdude supports a device,\r
- then that device is programmable. Use -F switch to ignore device codes. */\r
-#define AVRDEVCODE01 0x55 /* ATtiny12 */\r
-#define AVRDEVCODE02 0x56 /* ATtiny15 */\r
-#define AVRDEVCODE03 0x5E /* ATtiny261 */\r
-#define AVRDEVCODE04 0x76 /* ATmega8 */\r
-#define AVRDEVCODE05 0x74 /* ATmega16 */\r
-#define AVRDEVCODE06 0x72 /* ATmega32 */\r
-#define AVRDEVCODE07 0x45 /* ATmega64 */\r
-#define AVRDEVCODE08 0x74 /* ATmega644 */\r
-#define AVRDEVCODE09 0x43 /* ATmega128 */\r
-#define AVRDEVCODE10 0x63 /* ATmega162 */\r
-#define AVRDEVCODE11 0x78 /* ATmega169 */\r
-#define AVRDEVCODE12 0x6C /* AT90S4434 */\r
-#define AVRDEVCODE13 0x38 /* AT90S8515A */\r
-#define AVRDEVCODE14 0x65 /* AT90S8555 */\r
-\r
-\r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
- { Task: USB_USBTask , TaskStatus: TASK_STOP },\r
- { Task: CDC_Task , TaskStatus: TASK_STOP },\r
-};\r
-\r
-/* Globals: */\r
-/** Contains the current baud rate and other settings of the virtual serial port.\r
- *\r
- These values are set by the host via a class-specific request, and the physical USART should be reconfigured to match the\r
- new settings each time they are changed by the host.\r
- */\r
-CDC_Line_Coding_t LineCoding = { BaudRateBPS: 9600,\r
- CharFormat: OneStopBit,\r
- ParityType: Parity_None,\r
- DataBits: 8 };\r
-\r
-/** Ring (circular) buffer to hold the RX data - data from the host to the attached device on the serial port. */\r
-RingBuff_t Rx_Buffer;\r
-\r
-/** Ring (circular) buffer to hold the TX data - data from the attached device on the serial port to the host. */\r
-RingBuff_t Tx_Buffer;\r
-\r
-/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */\r
-volatile bool Transmitting = false;\r
-\r
-/* some global variables used throughout */\r
-uint16_t currAddress = 0;\r
-\r
-/** Main program entry point. This routine configures the hardware required by the application, then\r
- starts the scheduler to run the application tasks.\r
- */\r
-int main(void)\r
-{\r
- /* Disable watchdog if enabled by bootloader/fuses */\r
- MCUSR &= ~(1 << WDRF);\r
- wdt_disable();\r
-\r
- /* Disable clock division */\r
- clock_prescale_set(clock_div_1);\r
-\r
- /* Hardware Initialization */\r
- LEDs_Init();\r
- ReconfigureSPI();\r
-\r
- DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
- // PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)\r
- PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
- DDRD = 0;\r
- PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin\r
- // Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)\r
- DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);\r
- PORTB |= (1 << PB0);\r
- // make sure DataFlash devices to not interfere - deselect them by setting PE0 and PE1 HIGH:\r
- PORTE = 0xFF;\r
- DDRE = 0xFF;\r
-\r
- /* Ringbuffer Initialization */\r
- Buffer_Initialize(&Rx_Buffer);\r
- Buffer_Initialize(&Tx_Buffer);\r
- \r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
- \r
- /* Initialize Scheduler so that it can be used */\r
- Scheduler_Init();\r
-\r
- /* Initialize USB Subsystem */\r
- USB_Init();\r
-\r
- /* Scheduling - routine never returns, so put this last in the main function */\r
- Scheduler_Start();\r
-}\r
-\r
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and\r
- starts the library USB task to begin the enumeration and USB management process.\r
- */\r
-EVENT_HANDLER(USB_Connect)\r
-{\r
- /* Start USB management task */\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);\r
-\r
- /* Indicate USB enumerating */\r
- UpdateStatus(Status_USBEnumerating);\r
-}\r
-\r
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
- the status LEDs and stops the USB management and CDC management tasks.\r
- */\r
-EVENT_HANDLER(USB_Disconnect)\r
-{\r
- /* Stop running CDC and USB management tasks */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);\r
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);\r
-\r
- /* Indicate USB not ready */\r
- UpdateStatus(Status_USBNotReady);\r
-}\r
-\r
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
- of the USB device after enumeration - the device endpoints are configured and the CDC management task started.\r
- */\r
-EVENT_HANDLER(USB_ConfigurationChanged)\r
-{\r
- /* Setup CDC Notification, Rx and Tx Endpoints */\r
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,\r
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,\r
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,\r
- ENDPOINT_BANK_SINGLE);\r
-\r
- /* Indicate USB connected and ready */\r
- UpdateStatus(Status_USBReady);\r
-\r
- /* Start CDC task */\r
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
- control requests that are not handled internally by the USB library (including the CDC control commands,\r
- which are all issued via the control endpoint), so that they can be handled appropriately for the application.\r
- */\r
-EVENT_HANDLER(USB_UnhandledControlPacket)\r
-{\r
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;\r
-\r
- /* Process CDC specific control requests */\r
- switch (bRequest)\r
- {\r
- case REQ_GetLineEncoding:\r
- if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
- { \r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSetupReceived();\r
-\r
- /* Write the line coding data to the control endpoint */\r
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(LineCoding));\r
- \r
- /* Finalize the stream transfer to send the last packet or clear the host abort */\r
- Endpoint_ClearSetupOUT();\r
- }\r
- \r
- break;\r
- case REQ_SetLineEncoding:\r
- if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSetupReceived();\r
-\r
- /* Read the line coding data in from the host into the global struct */\r
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(LineCoding));\r
-\r
- /* Finalize the stream transfer to clear the last packet from the host */\r
- Endpoint_ClearSetupIN();\r
- \r
- /* Reconfigure the USART with the new settings */\r
- ReconfigureSPI();\r
- }\r
- \r
- break;\r
- case REQ_SetControlLineState:\r
- if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
- {\r
- /* Acknowledge the SETUP packet, ready for data transfer */\r
- Endpoint_ClearSetupReceived();\r
- \r
- /* Acknowledge status stage */\r
- while (!(Endpoint_IsSetupINReady()));\r
- Endpoint_ClearSetupIN();\r
- }\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */\r
-TASK(CDC_Task)\r
-{\r
- if (USB_IsConnected)\r
- {\r
- /* Select the Serial Rx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
- \r
- if (Endpoint_ReadWriteAllowed())\r
- {\r
- /* Read the received data endpoint into the transmission buffer */\r
- while (Endpoint_BytesInEndpoint())\r
- {\r
- /* Wait until the buffer has space for a new character */\r
- while (!((BUFF_STATICSIZE - Rx_Buffer.Elements)));\r
- \r
- /* Store each character from the endpoint */\r
- Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());\r
-\r
- /* Run the given command once enough data is available. */\r
- if (Rx_Buffer.Elements)\r
- {\r
- const uint8_t ZeroDataByteCommands[] = {'P', 'a', 'm', 'R', 'd', 'e', 'L', 's', 't', 'S', 'V', 'v', 'p', 'F'};\r
- const uint8_t OneDataByteCommands[] = {'T', 'c', 'C', 'D', 'l', 'f', 'x', 'y'};\r
- const uint8_t TwoDataByteCommands[] = {'A', 'Z'};\r
- const uint8_t ThreeDataByteCommands[] = {':'};\r
- const uint8_t FourDataByteCommands[] = {'.'};\r
- \r
- const struct\r
- {\r
- const uint8_t TotalCommands;\r
- const uint8_t* CommandBytes;\r
- } AVR910Commands[] = {{sizeof(ZeroDataByteCommands), ZeroDataByteCommands},\r
- {sizeof(OneDataByteCommands), OneDataByteCommands},\r
- {sizeof(TwoDataByteCommands), TwoDataByteCommands},\r
- {sizeof(ThreeDataByteCommands), ThreeDataByteCommands},\r
- {sizeof(FourDataByteCommands), FourDataByteCommands}};\r
- \r
- /* Determine the data length of the issued command */\r
- uint8_t CommandDataLength = (Rx_Buffer.Elements - 1);\r
- \r
- /* Loop through each of the possible command bytes allowable from the given command data length */\r
- for (uint8_t CurrentCommand = 0; CurrentCommand < AVR910Commands[CommandDataLength].TotalCommands; CurrentCommand++)\r
- {\r
- /* If issues command matches an allowable command, process it */\r
- if (Buffer_PeekElement(&Rx_Buffer) == AVR910Commands[CommandDataLength].CommandBytes[CurrentCommand])\r
- processHostSPIRequest();\r
- }\r
- }\r
- }\r
- \r
- /* Clear the endpoint buffer */\r
- Endpoint_ClearCurrentBank();\r
- }\r
-\r
- /* Select the Serial Tx Endpoint */\r
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
-\r
- /* Check if the Tx buffer contains anything to be sent to the host */\r
- if (Tx_Buffer.Elements)\r
- {\r
- /* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_ReadWriteAllowed()));\r
- \r
- /* Check before sending the data if the endpoint is completely full */\r
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);\r
- \r
- /* Write the transmission buffer contents to the received data endpoint */\r
- while (Tx_Buffer.Elements && (Endpoint_BytesInEndpoint() < CDC_TXRX_EPSIZE))\r
- Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));\r
- \r
- /* Send the data */\r
- Endpoint_ClearCurrentBank();\r
-\r
- /* If a full endpoint was sent, we need to send an empty packet afterwards to terminate the transfer */\r
- if (IsFull)\r
- {\r
- /* Wait until Serial Tx Endpoint Ready for Read/Write */\r
- while (!(Endpoint_ReadWriteAllowed()));\r
-\r
- /* Send an empty packet to terminate the transfer */\r
- Endpoint_ClearCurrentBank();\r
- }\r
- }\r
- }\r
-}\r
-\r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- * log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- * \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
- uint8_t LEDMask = LEDS_NO_LEDS;\r
- \r
- /* Set the LED mask to the appropriate LED mask based on the given status code */\r
- switch (CurrentStatus)\r
- {\r
- case Status_USBNotReady:\r
- LEDMask = (LEDS_LED1);\r
- break;\r
- case Status_USBEnumerating:\r
- LEDMask = (LEDS_LED1 | LEDS_LED2);\r
- break;\r
- case Status_USBReady:\r
- LEDMask = (LEDS_LED2 | LEDS_LED4);\r
- break;\r
- }\r
- \r
- /* Set the board LEDs to the new LED mask */\r
- LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
-/** Reconfigures SPI to match the current serial port settings issued by the host. */\r
-void ReconfigureSPI(void)\r
-{\r
- uint8_t SPCRmask = (1 << SPE) | (1 << MSTR); // always enable SPI as Master\r
- uint8_t SPSRmask = 0;\r
-\r
- /* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */\r
- /* For SPI, determine whether format is LSB or MSB */\r
- if (LineCoding.CharFormat == TwoStopBits) { \r
- SPCRmask |= (1 << DORD);\r
- } else if (LineCoding.CharFormat == OneStopBit) {\r
- SPCRmask |= (0 << DORD);\r
- }\r
-\r
- /* Determine data size - 5, 6, 7, or 8 bits are supported */\r
- /* Changing line coding changes SPI Mode\r
- CPOL=0, CPHA=0 Sample (Rising) Setup (Falling) SPI-Mode0 == 8 bits line coding\r
- CPOL=0, CPHA=1 Setup (Rising) Sample (Falling) SPI-Mode1 == 7 bits line coding\r
- CPOL=1, CPHA=0 Sample (Falling) Setup (Rising) SPI-Mode2 == 6 bits line coding\r
- CPOL=1, CPHA=1 Setup (Falling) Sample (Rising) SPI-Mode3 == 5 bits line coding\r
- */\r
- if (LineCoding.DataBits == 5) {\r
- SPCRmask |= ((1 << CPOL) | (1 << CPHA));\r
- } else if (LineCoding.DataBits == 6) {\r
- SPCRmask |= ((1 << CPOL) | (0 << CPHA));\r
- } else if (LineCoding.DataBits == 7) {\r
- SPCRmask |= ((0 << CPOL) | (1 << CPHA));\r
- } else if (LineCoding.DataBits == 8) {\r
- SPCRmask |= ((0 << CPOL) | (0 << CPHA));\r
- }\r
-\r
-\r
- /* Set the USART baud rate register to the desired baud rate value */\r
- /* also alter the SPI speed via value of baud rate */\r
- if (LineCoding.BaudRateBPS == 9600) { // 2Mhz SPI (Fosc / 4)\r
- SPCRmask |= ((0 << SPR1) | (0 << SPR0));\r
- SPSRmask |= (0 << SPI2X);\r
- } else if (LineCoding.BaudRateBPS == 14400) { // 1Mhz SPI (Fosc / 8)\r
- SPCRmask |= ((0 << SPR1) | (1 << SPR0));\r
- SPSRmask |= (1 << SPI2X);\r
- } else if (LineCoding.BaudRateBPS == 57600) { // 500kHz SPI (Fosc / 16)\r
- SPCRmask |= ((0 << SPR1) | (1 << SPR0));\r
- SPSRmask |= (0 << SPI2X);\r
- } else if (LineCoding.BaudRateBPS == 38400) { // 250kHz SPI (Fosc / 32)\r
- SPCRmask |= ((1 << SPR1) | (0 << SPR0));\r
- SPSRmask |= (1 << SPI2X);\r
- } else if (LineCoding.BaudRateBPS == 19200) { // 125kHz SPI (Fosc / 64)\r
- SPCRmask |= ((1 << SPR1) | (0 << SPR0));\r
- SPSRmask |= (0 << SPI2X);\r
- } else if (LineCoding.BaudRateBPS == 115200) { // 62.5kHz SPI (Fosc / 128)\r
- SPCRmask |= ((1 << SPR1) | (1 << SPR0));\r
- SPSRmask |= (0 << SPI2X);\r
- }\r
-\r
- SPCR = SPCRmask;\r
- SPSR = SPSRmask;\r
-}\r
-\r
-\r
-/* process data according to AVR910 protocol */\r
-void processHostSPIRequest(void) {\r
-\r
- uint8_t readByte1 = 0;\r
- uint8_t readByte2 = 0;\r
- uint8_t readByte3 = 0;\r
- uint8_t readByte4 = 0;\r
- uint8_t firstByte = 0;\r
-\r
- /* Taken from a90isp_ver23.asm:\r
- +-------------+------------+------+\r
- ;* Commands | Host writes | Host reads | |\r
- ;* -------- +-----+-------+------+-----+ |\r
- ;* | ID | data | data | | Note |\r
- ;* +-----------------------------------+-----+-------+------+-----+------+\r
- ;* | Enter programming mode | 'P' | | | 13d | 1 |\r
- ;* | Report autoincrement address | 'a' | | | 'Y' | |\r
- ;* | Set address | 'A' | ah al | | 13d | 2 |\r
- ;* | Write program memory, low byte | 'c' | dd | | 13d | 3 |\r
- ;* | Write program memory, high byte | 'C' | dd | | 13d | 3 |\r
- ;* | Issue Page Write | 'm' | | | 13d | |\r
- ;* | Read program memory | 'R' | |dd(dd)| | 4 |\r
- ;* | Write data memory | 'D' | dd | | 13d | |\r
- ;* | Read data memory | 'd' | | dd | | |\r
- ;* | Chip erase | 'e' | | | 13d | |\r
- ;* | Write lock bits | 'l' | dd | | 13d | |\r
- ;* | Write fuse bits | 'f' | dd | | 13d | 11 |\r
- ;* | Read fuse and lock bits | 'F' | | dd | | 11 |\r
- ;* | Leave programming mode | 'L' | | | 13d | 5 |\r
- ;* | Select device type | 'T' | dd | | 13d | 6 |\r
- ;* | Read signature bytes | 's' | | 3*dd | | |\r
- ;* | Return supported device codes | 't' | | n*dd | 00d | 7 |\r
- ;* | Return software identifier | 'S' | | s[7] | | 8 |\r
- ;* | Return sofware version | 'V' | |dd dd | | 9 |\r
- ;* | Return hardware version | 'v' | |dd dd | | 9 |\r
- ;* | Return programmer type | 'p' | | dd | | 10 |\r
- ;* | Set LED | 'x' | dd | | 13d | 12 |\r
- ;* | Clear LED | 'y' | dd | | 13d | 12 |\r
- ;* | Universial command | ':' | 3*dd | dd | 13d | |\r
- ;* | New universal command | '.' | 4*dd | dd | 13d | |\r
- ;* | Special test command | 'Z' | 2*dd | dd | | |\r
- */\r
-\r
- firstByte = Buffer_GetElement(&Rx_Buffer);\r
- Buffer_Initialize(&Tx_Buffer); // make sure the buffer is clear before proceeding\r
-\r
- if (firstByte == 'P') { // enter Programming mode\r
- // enable SPI -- already done\r
- // enter programming mode on target:\r
- //PORTB = 0; // set clock to zero\r
- RESETPORT = (1 << RESETPIN); // set RESET pin on target to 1\r
- RESETPORT2 = (1 << RESETPIN2);\r
- _delay_ms(DELAY_SHORT);\r
- //RESETPORT = (RESETPORT & ~(1 << RESETPIN)); // set RESET pin on target to 0 - Active\r
- RESETPORT = 0x00;\r
- RESETPORT2 = 0;\r
- _delay_ms(DELAY_SHORT);\r
- SPI_SendByte(0xAC);\r
- SPI_SendByte(0x53);\r
- SPI_SendByte(0x00);\r
- SPI_SendByte(0x00);\r
- _delay_ms(DELAY_VERYSHORT);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'T') { // Select device type\r
- Buffer_GetElement(&Rx_Buffer); // set device type\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'a') { // Report autoincrement address\r
- Buffer_StoreElement(&Tx_Buffer, 'Y'); // return 'Y' - Auto-increment enabled\r
-\r
- } else if (firstByte == 'A') { //Load Address\r
- // get two bytes over serial and set currAddress to them\r
- readByte1 = Buffer_GetElement(&Rx_Buffer); // high byte\r
- readByte2 = Buffer_GetElement(&Rx_Buffer); // low byte\r
- currAddress = (readByte1 << 8) | (readByte2);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'c') { // Write program memory, low byte\r
- // send 4 bytes over SPI; 0x40, then Address High Byte, then Low, then data\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- SPI_SendByte(0x40);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- SPI_SendByte(readByte1); // data\r
- _delay_ms(DELAY_MEDIUM); // certain MCUs require a delay of about 24585 cycles\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'C') { // Write program memory, high byte\r
- // send 4 bytes over SPI; 0x48, then Address High Byte, then Low, then data\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- SPI_SendByte(0x48);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- SPI_SendByte(readByte1); // data\r
- currAddress++; // increment currAddress\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'm') { // Write Program Memory Page\r
- // send 4 bytes over SPI; 0x4c, then Address High Byte, then Low, then 0x00\r
- SPI_SendByte(0x4C);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- SPI_SendByte(0x00);\r
- _delay_ms(DELAY_LONG);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'R') { // Read Program Memory\r
- // send 4 bytes over SPI; 0x28, then Address High Byte, then Low, then send back read data from 4th byte over serial\r
- SPI_SendByte(0x28);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- readByte1 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- // send 4 bytes over SPI; 0x20, then Address High Byte, then Low, then send back read data from 4th byte over serial\r
- SPI_SendByte(0x20);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- readByte2 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte2);\r
- currAddress++; // increment currAddress\r
-\r
- } else if (firstByte == 'D') { // Write Data Memory\r
- // send 4 bytes over SPI; 0xc0, then Address High Byte, then Low, then data\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- SPI_SendByte(0xC0);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- SPI_SendByte(readByte1); // data\r
- _delay_ms(DELAY_MEDIUM);\r
- currAddress++; // increment currAddress\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'd') { // Read Data Memory\r
- // send 4 bytes over SPI; 0xa0, then Address High Byte, then Low, then send back read data from 4th byte over serial\r
- SPI_SendByte(0xA0);\r
- SPI_SendByte((currAddress >> 8)); // high byte\r
- SPI_SendByte((currAddress)); // low byte\r
- readByte1 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- currAddress++; // increment currAddress\r
-\r
- } else if (firstByte == 'e') { // erase the target device\r
- // send 4 bytes over SPI; 0xac, 0x80, 0x04, 0x00\r
- SPI_SendByte(0xAC);\r
- SPI_SendByte(0x80);\r
- SPI_SendByte(0x04);\r
- SPI_SendByte(0x00);\r
- _delay_ms(DELAY_LONG);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'l') { // write lock bits\r
- // send 4 bytes over SPI; 0xac, [andi s_data 0x06], 0xe0, 0x00\r
- readByte1 = Buffer_GetElement(&Rx_Buffer); // read in lock bits data\r
- SPI_SendByte(0xAC);\r
- SPI_SendByte(((0x06 & readByte1) | 0xE0)); // TODO - is this correct???\r
- SPI_SendByte(0x00);\r
- SPI_SendByte(0x00);\r
- _delay_ms(DELAY_MEDIUM);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'f') { // write fuse bits\r
- // ignore this command, but need to remove data from the receive buffer\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'L') { // leave programming mode\r
- RESETPORT |= (1 << RESETPIN); // set RESET pin on target to 1\r
- RESETPORT2 |= (1 << RESETPIN2); // set RESET pin on target to 1\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 's') { // Read signature bytes\r
- // send 4 bytes over SPI; 0x30, 0x00, 0x02, read and send last byte over serial\r
- SPI_SendByte(0x30);\r
- SPI_SendByte(0x00);\r
- SPI_SendByte(0x02);\r
- readByte1 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- SPI_SendByte(0x30);\r
- SPI_SendByte(0x00);\r
- SPI_SendByte(0x01);\r
- readByte1 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- SPI_SendByte(0x30);\r
- SPI_SendByte(0x00);\r
- SPI_SendByte(0x00);\r
- readByte1 = SPI_TransferByte(0x00); // read in data\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
-\r
- } else if (firstByte == 't') { // Return supported device codes\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE01);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE02);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE03);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE04);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE05);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE06);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE07);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE08);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE09);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE10);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE11);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE12);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE13);\r
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE14);\r
- Buffer_StoreElement(&Tx_Buffer, 0x00);\r
-\r
- } else if (firstByte == 'S') { // Return software identifier\r
- // return string[7] with "AVR ISP"\r
- Buffer_StoreElement(&Tx_Buffer, 'A');\r
- Buffer_StoreElement(&Tx_Buffer, 'V');\r
- Buffer_StoreElement(&Tx_Buffer, 'R');\r
- Buffer_StoreElement(&Tx_Buffer, 0x20);\r
- Buffer_StoreElement(&Tx_Buffer, 'I');\r
- Buffer_StoreElement(&Tx_Buffer, 'S');\r
- Buffer_StoreElement(&Tx_Buffer, 'P');\r
-\r
- } else if (firstByte == 'V') { // Return sofware version\r
- //return two bytes, software Major then Minor\r
- Buffer_StoreElement(&Tx_Buffer, '2');\r
- Buffer_StoreElement(&Tx_Buffer, '3');\r
-\r
- } else if (firstByte == 'v') { // Return hardware version\r
- //return two bytes, hardware Major then Minor \r
- Buffer_StoreElement(&Tx_Buffer, ('1'));\r
- Buffer_StoreElement(&Tx_Buffer, ('0'));\r
-\r
- } else if (firstByte == 'p') { // Return programmer type\r
- // return 'S' for Serial Programmer\r
- Buffer_StoreElement(&Tx_Buffer, 'S');\r
-\r
- } else if (firstByte == 'x') { // set LED\r
- // ignore this command, but need to remove data from the receive buffer\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'y') { // clear LED\r
- // ignore this command, but need to remove data from the receive buffer\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == ':') { // Universal Command\r
- // get 3 bytes over serial\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- readByte2 = Buffer_GetElement(&Rx_Buffer);\r
- readByte3 = Buffer_GetElement(&Rx_Buffer);\r
- SPI_SendByte(readByte1);\r
- SPI_SendByte(readByte2);\r
- SPI_SendByte(readByte3);\r
- readByte1 = SPI_TransferByte(0x00);\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- _delay_ms(DELAY_MEDIUM);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == '.') { // New Universal Command\r
- // get 4 bytes over serial\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- readByte2 = Buffer_GetElement(&Rx_Buffer);\r
- readByte3 = Buffer_GetElement(&Rx_Buffer);\r
- readByte4 = Buffer_GetElement(&Rx_Buffer);\r
- SPI_SendByte(readByte1);\r
- SPI_SendByte(readByte2);\r
- SPI_SendByte(readByte3);\r
- readByte1 = SPI_TransferByte(readByte4);\r
- Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- _delay_ms(DELAY_MEDIUM);\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
-\r
- } else if (firstByte == 'Z') { // Special test command\r
- // do nothing, but need to remove data from the receive buffer\r
- readByte1 = Buffer_GetElement(&Rx_Buffer);\r
- readByte2 = Buffer_GetElement(&Rx_Buffer);\r
-\r
- } else {\r
- // do nothing, but need to return with a carriage return\r
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
- }\r
-}\r
-\r