Cleaned up bootloader code
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 14 Jan 2017 08:54:20 +0000 (00:54 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 14 Jan 2017 08:54:20 +0000 (00:54 -0800)
avr/src/xboot/eeprom_driver.c [deleted file]
avr/src/xboot/eeprom_driver.h [deleted file]
avr/src/xboot/protocol.h [deleted file]
avr/src/xboot/sp_driver.S
avr/src/xboot/sp_driver.h
avr/src/xboot/uart.c [deleted file]
avr/src/xboot/uart.h [deleted file]
avr/src/xboot/watchdog.c [deleted file]
avr/src/xboot/watchdog.h [deleted file]
avr/src/xboot/xboot.c
avr/src/xboot/xboot.h

diff --git a/avr/src/xboot/eeprom_driver.c b/avr/src/xboot/eeprom_driver.c
deleted file mode 100644 (file)
index 38b6eea..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/************************************************************************/
-/* XMEGA EEPROM Driver                                                  */
-/*                                                                      */
-/* eeprom.c                                                             */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2011 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#include "eeprom_driver.h"
-
-
-static inline void NVM_EXEC(void) {
-  void *z = (void *)&NVM_CTRLA;
-
-  __asm__ volatile("out %[ccp], %[ioreg]"  "\n\t"
-                   "st z, %[cmdex]"
-                   :
-                   : [ccp] "I" (_SFR_IO_ADDR(CCP)),
-                   [ioreg] "d" (CCP_IOREG_gc),
-                   [cmdex] "r" (NVM_CMDEX_bm),
-                     [z] "z" (z)
-                   );
-}
-
-
-void wait_for_nvm() {
-  while (NVM.STATUS & NVM_NVMBUSY_bm) continue;
-}
-
-
-void EEPROM_erase_all() {
-  wait_for_nvm();
-  NVM.CMD = NVM_CMD_ERASE_EEPROM_gc;
-  NVM_EXEC();
-}
diff --git a/avr/src/xboot/eeprom_driver.h b/avr/src/xboot/eeprom_driver.h
deleted file mode 100644 (file)
index c139a43..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/************************************************************************/
-/* XMEGA EEPROM Driver                                                  */
-/*                                                                      */
-/* eeprom.h                                                             */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2011 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#pragma once
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <avr/eeprom.h>
-
-#include "xboot.h"
-
-#ifndef EEPROM_PAGE_SIZE
-#define EEPROM_PAGE_SIZE E2PAGESIZE
-#endif
-
-#define EEPROM_read_byte(addr) \
-  eeprom_read_byte((const uint8_t *)((uint16_t)(addr)))
-
-#define EEPROM_write_byte(addr, value) \
-  eeprom_write_byte((uint8_t *)((uint16_t)(addr)), (value))
-
-#define EEPROM_read_block(addr, dest, len) \
-  eeprom_read_block((dest), (void *)((uint16_t)(addr)), (len))
-
-#define EEPROM_write_block(addr, src, len) \
-  eeprom_write_block((src), (void *)((uint16_t)(addr)), (len))
-
-void EEPROM_erase_all();
diff --git a/avr/src/xboot/protocol.h b/avr/src/xboot/protocol.h
deleted file mode 100644 (file)
index 4336094..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* XBoot Protocol Definition                                            */
-/*                                                                      */
-/* protocol.h                                                           */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#pragma once
-
-#include "xboot.h"
-
-// General Commands
-#define CMD_SYNC                '\x1b'
-
-// Informational Commands
-#define CMD_CHECK_AUTOINCREMENT 'a'
-#define CMD_CHECK_BLOCK_SUPPORT 'b'
-#define CMD_PROGRAMMER_TYPE     'p'
-#define CMD_DEVICE_CODE         't'
-#define CMD_PROGRAM_ID          'S'
-#define CMD_VERSION             'V'
-#define CMD_READ_SIGNATURE      's'
-
-// Addressing
-#define CMD_SET_ADDRESS         'A'
-#define CMD_SET_EXT_ADDRESS     'H'
-
-// Erase
-#define CMD_CHIP_ERASE          'e'
-
-// Block Access
-#define CMD_BLOCK_LOAD          'B'
-#define CMD_BLOCK_READ          'g'
-
-// Byte Access
-#define CMD_READ_BYTE           'R'
-#define CMD_WRITE_LOW_BYTE      'c'
-#define CMD_WRITE_HIGH_BYTE     'C'
-#define CMD_WRITE_PAGE          'm'
-#define CMD_WRITE_EEPROM_BYTE   'D'
-#define CMD_READ_EEPROM_BYTE    'd'
-
-// Lock and Fuse Bits
-#define CMD_WRITE_LOCK_BITS     'l'
-#define CMD_READ_LOCK_BITS      'r'
-#define CMD_READ_LOW_FUSE_BITS  'F'
-#define CMD_READ_HIGH_FUSE_BITS 'N'
-#define CMD_READ_EXT_FUSE_BITS  'Q'
-
-// Bootloader Commands
-#define CMD_ENTER_PROG_MODE     'P'
-#define CMD_LEAVE_PROG_MODE     'L'
-#define CMD_EXIT_BOOTLOADER     'E'
-#define CMD_SET_LED             'x'
-#define CMD_CLEAR_LED           'y'
-#define CMD_SET_TYPE            'T'
-
-#define CMD_CRC                 'h'
-
-// Memory types for block access
-#define MEM_EEPROM              'E'
-#define MEM_FLASH               'F'
-#define MEM_USERSIG             'U'
-#define MEM_PRODSIG             'P'
-
-// Sections for CRC checks
-#define SECTION_FLASH           'F'
-#define SECTION_APPLICATION     'A'
-#define SECTION_BOOT            'B'
-#define SECTION_APP             'a'
-#define SECTION_APP_TEMP        't'
-
-// Command Responses
-#define REPLY_ACK               '\r'
-#define REPLY_YES               'Y'
-#define REPLY_ERROR             '?'
index e6fff991969dfb5978b884b5cb2f6a401b29d069..bbb1ee7b9a0459bbe7bccf4f3662d2ac7b4688cc 100644 (file)
@@ -1,41 +1,4 @@
 ;******************************************************************************
-;*
-;* XMEGA Self-programming driver assembly source file.
-;*
-;*      This file contains the low-level implementations for the
-;*      XMEGA Self-programming driver. It is written for the GCC Assembler.
-;*
-;*      If any SPM instructions are used, the linker file must define
-;*      a segment named bootloader which must be located in the device Boot section.
-;*      This can be done by passing "-Wl,--section-start=.BOOT=0x020000" to the
-;*      linker with the correct address for the boot section.
-;*
-;*      None of these routines clean up the NVM Command Register after use.
-;*      It is therefore important to write NVM_CMD_NO_OPERATION_gc (0x00) to this
-;*      register when you are finished using any of the functions in this driver.
-;*
-;*      For all routines, it is important that any interrupt handlers do not
-;*      perform any NVM operations. The user must implement a scheme for mutually
-;*      exclusive access to the NVM. However, the 4-cycle timeout will work fine,
-;*      since writing to the Configuration Change Protection register (CCP)
-;*      automatically disables interrupts for 4 instruction cycles.
-;*
-;*      Note on IAR calling convention:
-;*         Scratch registers:   R18-R27, R30-R31
-;*         Preserved registers: R2-R17, R28-R29
-;*         Parameter registers: R8-R25 (2-,4-, or 8- byte alignment)
-;*         Return registers:    R18-R25 (up to 64-bit)
-;*
-;* Application note:
-;*      AVR1316: XMEGA Self-programming
-;*
-;* Documentation
-;*      For comprehensive code documentation, supported compilers, compiler
-;*      settings and supported devices see readme.html
-;*
-;*      Atmel Corporation: http:;www.atmel.com \n
-;*      Support email: avr@atmel.com
-;*
 ;* $Revision: 1153 $
 ;* $Date: 2007-12-18 09:48:23 +0100 (ti, 18 des 2007) $
 ;*
 ;* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 ;* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ;******************************************************************************
+;*
+;* XMEGA Self-programming driver assembly source file.
+;*
+;*      This file contains the low-level implementations for the
+;*      XMEGA Self-programming driver. It is written for the GCC Assembler.
+;*
+;*      If any SPM instructions are used, the linker file must define a segment
+;*      named bootloader which must be located in the device Boot section.
+;*      This can be done by passing "-Wl,--section-start=.BOOT=0x020000" to the
+;*      linker with the correct address for the boot section.
+;*
+;*      None of these routines clean up the NVM Command Register after use. It
+;*      is therefore important to write NVM_CMD_NO_OPERATION_gc (0x00) to this
+;*      register when finished using any of the functions in this driver.
+;*
+;*      For all routines, it is important that any interrupt handlers do not
+;*      perform NVM operations. The user must implement a scheme for mutually
+;*      exclusive access to NVM. However, the 4-cycle timeout will work fine,
+;*      since writing to the Configuration Change Protection register (CCP)
+;*      automatically disables interrupts for 4 instruction cycles.
+;*
+;*      Note on IAR calling convention:
+;*         Scratch registers:   R18-R27, R30-R31
+;*         Preserved registers: R2-R17, R28-R29
+;*         Parameter registers: R8-R25 (2-,4-, or 8- byte alignment)
+;*         Return registers:    R18-R25 (up to 64-bit)
+;*
+;* Application note:
+;*      AVR1316: XMEGA Self-programming
+;*
+;* Documentation
+;*      For comprehensive code documentation, supported compilers, compiler
+;*      settings and supported devices see readme.html
+;*
+;*      Atmel Corporation: http:;www.atmel.com \n
+;*      Support email: avr@atmel.com
 
 #include <avr/io.h>
-;#include "Flash_Defines.h"
-
-/* Define the size of the flash page if not defined in the header files. */
-#ifndef APP_SECTION_PAGE_SIZE
-       #error  APP_SECTION_PAGE_SIZE must be defined if not defined in header files.
-       //#define APP_SECTION_PAGE_SIZE 512
-#endif /*APP_SECTION_PAGE_SIZE*/
-
-/* Defines not yet included in header file. */
-#define NVM_CMD_NO_OPERATION_gc (0x00<<0)      // Noop/Ordinary LPM
-#define NVM_CMD_READ_USER_SIG_ROW_gc (0x01<<0) // Read user signature row
-#define NVM_CMD_READ_CALIB_ROW_gc (0x02<<0)    // Read calibration row
-#define NVM_CMD_READ_EEPROM_gc (0x06<<0)       // Read EEPROM
-#define NVM_CMD_READ_FUSES_gc (0x07<<0)        // Read fuse byte
-#define NVM_CMD_WRITE_LOCK_BITS_gc (0x08<<0)   // Write lock bits
-#define NVM_CMD_ERASE_USER_SIG_ROW_gc (0x18<<0)        // Erase user signature row
-#define NVM_CMD_WRITE_USER_SIG_ROW_gc (0x1A<<0)        // Write user signature row
-#define NVM_CMD_ERASE_APP_gc (0x20<<0) // Erase Application Section
-#define NVM_CMD_ERASE_APP_PAGE_gc (0x22<<0)    // Erase Application Section page
-#define NVM_CMD_LOAD_FLASH_BUFFER_gc (0x23<<0) // Load Flash page buffer
-#define NVM_CMD_WRITE_APP_PAGE_gc (0x24<<0)    // Write Application Section page
-#define NVM_CMD_ERASE_WRITE_APP_PAGE_gc (0x25<<0)      // Erase-and-write Application Section page
-#define NVM_CMD_ERASE_FLASH_BUFFER_gc (0x26<<0)        // Erase/flush Flash page buffer
-#define NVM_CMD_ERASE_BOOT_PAGE_gc (0x2A<<0)   // Erase Boot Section page
-#define NVM_CMD_WRITE_BOOT_PAGE_gc (0x2C<<0)   // Write Boot Section page
-#define NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc (0x2D<<0)     // Erase-and-write Boot Section page
-#define NVM_CMD_ERASE_EEPROM_gc (0x30<<0)      // Erase EEPROM
-#define NVM_CMD_ERASE_EEPROM_PAGE_gc (0x32<<0) // Erase EEPROM page
-#define NVM_CMD_LOAD_EEPROM_BUFFER_gc (0x33<<0)        // Load EEPROM page buffer
-#define NVM_CMD_WRITE_EEPROM_PAGE_gc (0x34<<0) // Write EEPROM page
-#define NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc (0x35<<0)   // Erase-and-write EEPROM page
-#define NVM_CMD_ERASE_EEPROM_BUFFER_gc (0x36<<0)       // Erase/flush EEPROM page buffer
-#define NVM_CMD_APP_CRC_gc (0x38<<0)   // Generate Application section CRC
-#define NVM_CMD_BOOT_CRC_gc (0x39<<0)  // Generate Boot Section CRC
-#define NVM_CMD_FLASH_RANGE_CRC_gc (0x3A<<0)   // Generate Flash Range CRC
-#define CCP_SPM_gc (0x9D<<0)   // SPM Instruction Protection
-#define CCP_IOREG_gc (0xD8<<0) // IO Register Protection
-
-
-
-; ---
-; This routine reads a byte from flash given by the address in
-; R25:R24:R23:R22.
-;
-; Input:
-;     R25:R24:R23:R22.
-;
-; Returns:
-;     R24 - Read byte.
-; ---
 
+; Defines not yet included in header file.
+#define NVM_CMD_NO_OPERATION_gc            0x00
+#define NVM_CMD_READ_USER_SIG_ROW_gc       0x01
+#define NVM_CMD_READ_CALIB_ROW_gc          0x02
+#define NVM_CMD_READ_EEPROM_gc             0x06
+#define NVM_CMD_READ_FUSES_gc              0x07
+#define NVM_CMD_WRITE_LOCK_BITS_gc         0x08
+#define NVM_CMD_ERASE_USER_SIG_ROW_gc      0x18
+#define NVM_CMD_WRITE_USER_SIG_ROW_gc      0x1a
+#define NVM_CMD_ERASE_APP_gc               0x20
+#define NVM_CMD_ERASE_APP_PAGE_gc          0x22
+#define NVM_CMD_LOAD_FLASH_BUFFER_gc       0x23
+#define NVM_CMD_WRITE_APP_PAGE_gc          0x24
+#define NVM_CMD_ERASE_WRITE_APP_PAGE_gc    0x25
+#define NVM_CMD_ERASE_FLASH_BUFFER_gc      0x26
+#define NVM_CMD_ERASE_BOOT_PAGE_gc         0x2a
+#define NVM_CMD_WRITE_BOOT_PAGE_gc         0x2c
+#define NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc   0x2d
+#define NVM_CMD_ERASE_EEPROM_gc            0x30
+#define NVM_CMD_ERASE_EEPROM_PAGE_gc       0x32
+#define NVM_CMD_LOAD_EEPROM_BUFFER_gc      0x33
+#define NVM_CMD_WRITE_EEPROM_PAGE_gc       0x34
+#define NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc 0x35
+#define NVM_CMD_ERASE_EEPROM_BUFFER_gc     0x36
+#define NVM_CMD_APP_CRC_gc                 0x38
+#define NVM_CMD_BOOT_CRC_gc                0x39
+#define NVM_CMD_FLASH_RANGE_CRC_gc         0x3a
+#define CCP_SPM_gc                         0x9d
+#define CCP_IOREG_gc                       0xd8
+
+
+; Reads a byte from flash given by the address in R25:R24:R23:R22.
+;
+; Input: R25:R24:R23:R22.
+; Returns: R24 - Read byte.
 .section .text
 .global SP_ReadByte
 
 SP_ReadByte:
-       in      r19, RAMPZ      ; Save RAMPZ.
-       out     RAMPZ, r24      ; Load RAMPZ with the MSB of the address.
-       movw    ZL, r22         ; Move the low bytes to the Z pointer
-       elpm    r24, Z          ; Extended load byte from address pointed to by Z.
-       out     RAMPZ, r19      ; Restore RAMPZ register.
-       ret
+    in   r19, RAMPZ      ; Save RAMPZ.
+    out  RAMPZ, r24      ; Load RAMPZ with the MSB of the address.
+    movw ZL, r22         ; Move the low bytes to the Z pointer
+    elpm r24, Z          ; Extended load byte from address pointed to by Z.
+    out  RAMPZ, r19      ; Restore RAMPZ register.
+    ret
 
 
-
-; ---
-; This routine reads a word from flash given by the address in
-; R25:R24:R23:R22.
-;
-; Input:
-;     R25:R24:R23:R22.
+; Reads a word from flash given by the address in R25:R24:R23:R22.
 ;
-; Returns:
-;     R25:R24 - Read word.
-; ---
-
+; Input: R25:R24:R23:R22.
+; Returns: R25:R24 - Read word.
 .section .text
 .global SP_ReadWord
 
 SP_ReadWord:
-       in      r19, RAMPZ      ; Save RAMPZ.
-       out     RAMPZ, r24      ; Load RAMPZ with the MSB of the address.
-       movw    ZL, r22         ; Move the low bytes to the Z pointer
-       elpm    r24, Z+         ; Extended load byte from address pointed to by Z.
-       elpm    r25, Z          ; Extended load byte from address pointed to by Z.
-       out     RAMPZ, r19      ; Restore RAMPZ register.
-       ret
+    in   r19, RAMPZ      ; Save RAMPZ.
+    out  RAMPZ, r24      ; Load RAMPZ with the MSB of the address.
+    movw ZL, r22         ; Move the low bytes to the Z pointer
+    elpm r24, Z+         ; Extended load byte from address pointed to by Z.
+    elpm r25, Z          ; Extended load byte from address pointed to by Z.
+    out  RAMPZ, r19      ; Restore RAMPZ register.
+    ret
 
 
-
-; ---
-; This routine reads the calibration byte given by the index in R24.
-;
-; Input:
-;     R24 - Byte index.
+; Reads the calibration byte given by the index in R24.
 ;
-; Returns:
-;     R24 - Calibration byte.
-; ---
-
+; Input: R24 - Byte index.
+; Returns: R24 - Calibration byte.
 .section .text
-.global SP_ReadCalibrationByte 
+.global SP_ReadCalibrationByte
 
 SP_ReadCalibrationByte:
-       ldi     r20, NVM_CMD_READ_CALIB_ROW_gc    ; Prepare NVM command in R20.
-       rjmp    SP_CommonLPM                      ; Jump to common LPM code.
+    ldi  r20, NVM_CMD_READ_CALIB_ROW_gc    ; Prepare NVM command in R20.
+    rjmp SP_CommonLPM                      ; Jump to common LPM code.
 
 
-
-; ---
-; This routine reads the user signature byte given by the index in R25:R24.
-;
-; Input:
-;     R25:R24 - Byte index.
+; Reads the user signature byte given by the index in R25:R24.
 ;
-; Returns:
-;     R24 - Signature byte.
-; ---
-
-.section .text 
+; Input: R25:R24 - Byte index.
+; Returns: R24 - Signature byte.
+.section .text
 .global SP_ReadUserSignatureByte
 
 SP_ReadUserSignatureByte:
-       ldi     r20, NVM_CMD_READ_USER_SIG_ROW_gc  ; Prepare NVM command in R20.
-       rjmp    SP_CommonLPM                       ; Jump to common LPM code.
+    ldi  r20, NVM_CMD_READ_USER_SIG_ROW_gc  ; Prepare NVM command in R20.
+    rjmp SP_CommonLPM                       ; Jump to common LPM code.
 
 
-
-; ---
-; This routine reads the fuse byte given by the index in R24.
+; Reads the fuse byte given by the index in R24.
 ;
-; Input:
-;     R24 - Byte index.
-;
-; Returns:
-;     R24 - Fuse byte.
-; ---
-
-.section .text 
+; Input: R24 - Byte index.
+; Returns: R24 - Fuse byte.
+.section .text
 .global SP_ReadFuseByte
 
 SP_ReadFuseByte:
-       sts     NVM_ADDR0, r24              ; Load fuse byte index into NVM Address Register 0.
-       clr     r24                         ; Prepare a zero.
-       sts     NVM_ADDR1, r24              ; Load zero into NVM Address Register 1.
-       sts     NVM_ADDR2, r24              ; Load zero into NVM Address Register 2.
-       ldi     r20, NVM_CMD_READ_FUSES_gc  ; Prepare NVM command in R20.
-       rcall   SP_CommonCMD                ; Jump to common NVM Action code.
-       movw    r24, r22                    ; Move low byte to 1 byte return address.
-       ret
-
-
-
-; ---
-; This routine sets the lock bits from R24. Note that unlocking is only
-; possible by doing a full chip erase, not available from software.
-;
-; Input:
-;     R24 - Lock bits.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text 
-.global SP_WriteLockBits
+    sts   NVM_ADDR0, r24             ; Load fuse index into NVM Address Reg 0.
+    clr   r24                        ; Prepare a zero.
+    sts   NVM_ADDR1, r24             ; Load zero into NVM Address Register 1.
+    sts   NVM_ADDR2, r24             ; Load zero into NVM Address Register 2.
+    ldi   r20, NVM_CMD_READ_FUSES_gc ; Prepare NVM command in R20.
+    rcall SP_CommonCMD               ; Jump to common NVM Action code.
+    movw  r24, r22                   ; Move low byte to 1 byte return address.
+    ret
 
-SP_WriteLockBits:
-       sts     NVM_DATA0, r24                  ; Load lock bits into NVM Data Register 0.
-       ldi     r20, NVM_CMD_WRITE_LOCK_BITS_gc ; Prepare NVM command in R20.
-       rjmp    SP_CommonCMD                    ; Jump to common NVM Action code.
-
-
-
-; ---
-; This routine reads the lock bits.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     R24 - Lock bits.
-; ---
-
-.section .text         
-.global SP_ReadLockBits
-
-SP_ReadLockBits:
-       lds     r24, NVM_LOCKBITS       ; Read IO-mapped lock bits.
-       ret
-
-
-
-; ---
-; This routine erases the user signature row.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
 
+; Erases the user signature row.
 .section .text
 .global SP_EraseUserSignatureRow
 
 SP_EraseUserSignatureRow:
-       in      r19, RAMPZ                         ; Save RAMPZ, which is restored in SP_CommonSPM.
-       ldi     r20, NVM_CMD_ERASE_USER_SIG_ROW_gc ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                       ; Jump to common SPM code.
+    in  r19, RAMPZ                       ; Save RAMPZ, restored in SP_CommonSPM.
+    ldi r20, NVM_CMD_ERASE_USER_SIG_ROW_gc ; Prepare NVM command in R20.
+    jmp SP_CommonSPM                       ; Jump to common SPM code.
 
 
-
-; ---
-; This routine writes the flash buffer to the user signature row.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
-
+; Writes the flash buffer to the user signature row.
 .section .text
 .global SP_WriteUserSignatureRow
 
 SP_WriteUserSignatureRow:
-       in      r19, RAMPZ                          ; Save RAMPZ, which is restored in SP_CommonSPM.
-       ldi     r20, NVM_CMD_WRITE_USER_SIG_ROW_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                        ; Jump to common SPM code.
-
-
+    in  r19, RAMPZ                       ; Save RAMPZ, restored in SP_CommonSPM.
+    ldi r20, NVM_CMD_WRITE_USER_SIG_ROW_gc  ; Prepare NVM command in R20.
+    jmp SP_CommonSPM                        ; Jump to common SPM code.
 
-; ---
-; This routine erases the entire application section.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
 
+; Erases the entire application section.
 .section .text
 .global SP_EraseApplicationSection
 
 SP_EraseApplicationSection:
-       in      r19, RAMPZ                 ; Save RAMPZ, which is restored in SP_CommonSPM.
-       clr     r24                        ; Prepare a zero.
-       clr     r25
-       out     RAMPZ, r24                 ; Point into Application area.
-       ldi     r20, NVM_CMD_ERASE_APP_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM               ; Jump to common SPM code.
-
+    in  r19, RAMPZ                 ; Save RAMPZ, restored in SP_CommonSPM.
+    clr r24                        ; Prepare a zero.
+    clr r25
+    out RAMPZ, r24                 ; Point into Application area.
+    ldi r20, NVM_CMD_ERASE_APP_gc  ; Prepare NVM command in R20.
+    jmp SP_CommonSPM               ; Jump to common SPM code.
 
 
-; ---
-; This routine erases the page at address R25:R24:R23:R22 in the application
-; section. The address can point anywhere inside the page.
-;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text 
-.global SP_EraseApplicationPage
-
-SP_EraseApplicationPage:
-       in      r19, RAMPZ                      ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                      ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                        ; Move low bytes for ZH:ZL to R25:R24
-       ldi     r20, NVM_CMD_ERASE_APP_PAGE_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                    ; Jump to common SPM code.
-
-
-
-; ---
-; This routine writes the word from R23:R22 into the Flash page buffer at
-; address R25:R24.
+; Writes the word from R23:R22 into the Flash page buffer at address R25:R24.
 ;
 ; Input:
 ;     R25:R24 - Byte address into Flash page.
 ;     R23:R22 - Word to write.
-;
-; Returns:
-;     Nothing.
-; ---
-
 .section .text
 .global SP_LoadFlashWord
 
 SP_LoadFlashWord:
-       in      r19, RAMPZ                         ; Save RAMPZ, which is restored in SP_CommonSPM.
-       movw    r0, r22                            ; Prepare flash word in R1:R0.
-       ldi     r20, NVM_CMD_LOAD_FLASH_BUFFER_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                       ; Jump to common SPM code.
-
+    in   r19, RAMPZ                      ; Save RAMPZ, restored in SP_CommonSPM.
+    movw r0, r22                            ; Prepare flash word in R1:R0.
+    ldi  r20, NVM_CMD_LOAD_FLASH_BUFFER_gc  ; Prepare NVM command in R20.
+    jmp  SP_CommonSPM                       ; Jump to common SPM code.
 
 
-; ---
-; This routine writes an entire page from the SRAM buffer at
+; Writes an entire page from the SRAM buffer at
 ; address R25:R24 into the Flash page buffer.
 ;
 ; Note that you must define "-Wl,--section-start=.BOOT=0x020000" for the
 ; linker to place this function in the boot section with the correct address.
 ;
-; Input:
-;     R25:R24 - 16-bit pointer to SRAM buffer.
-;
-; Returns:
-;     Nothing.
-; ---
-               
+; Input: R25:R24 - 16-bit pointer to SRAM buffer.
 .section .text
 .global SP_LoadFlashPage
 
 SP_LoadFlashPage:
-       clr     ZL              ; Clear low byte of Z, to indicate start of page.
-       clr     ZH              ; Clear high byte of Z, to indicate start of page.
+    clr  ZL              ; Clear low byte of Z, to indicate start of page.
+    clr  ZH              ; Clear high byte of Z, to indicate start of page.
 
-       out     RAMPX, r1       ; Clear RAMPX pointer.
-       movw    XL, r24         ; Load X with data buffer address.
+    out  RAMPX, r1       ; Clear RAMPX pointer.
+    movw XL, r24         ; Load X with data buffer address.
 
-       ldi     r20, NVM_CMD_LOAD_FLASH_BUFFER_gc  ; Prepare NVM command code in R20.
-       sts     NVM_CMD, r20                       ; Load it into NVM command register.
+    ldi r20, NVM_CMD_LOAD_FLASH_BUFFER_gc  ; Prepare NVM command code in R20.
+    sts NVM_CMD, r20                       ; Load it into NVM command register.
 
 #if APP_SECTION_PAGE_SIZE > 512
-       ldi     r22, ((APP_SECTION_PAGE_SIZE/2) >> 8)
+    ldi r22, ((APP_SECTION_PAGE_SIZE / 2) >> 8)
 #endif
-
-       ldi     r21, ((APP_SECTION_PAGE_SIZE/2)&0xFF)    ; Load R21 with page word count.
-       ldi     r18, CCP_SPM_gc                    ; Prepare Protect SPM signature in R16.
+    ldi r21, ((APP_SECTION_PAGE_SIZE / 2) & 0xff) ; Load R21 page word count.
+    ldi r18, CCP_SPM_gc                  ; Prepare Protect SPM signature in R16.
 
 SP_LoadFlashPage_1:
-       ld      r0, X+         ; Load low byte from buffer into R0.
-       ld      r1, X+         ; Load high byte from buffer into R1.
-       sts     CCP, r18       ; Enable SPM operation (this disables interrupts for 4 cycles).
-       spm                    ; Self-program.
-       adiw    ZL, 2          ; Move Z to next Flash word.
+    ld  r0, X+        ; Load low byte from buffer into R0.
+    ld  r1, X+        ; Load high byte from buffer into R1.
+    sts CCP, r18      ; Enable SPM operation (disables interrupts for 4 cycles).
+    spm               ; Self-program.
+    adiw ZL, 2        ; Move Z to next Flash word.
 
 #if APP_SECTION_PAGE_SIZE > 512
-       subi    r21, 1         ; Decrement word count.
-       sbci    r22, 0
+    subi r21, 1         ; Decrement word count.
+    sbci r22, 0
 #else
-       dec     r21            ; Decrement word count.
+    dec r21             ; Decrement word count.
 #endif
 
-       brne    SP_LoadFlashPage_1   ; Repeat until word cont is zero.
-
-       clr     r1                   ; Clear R1 for GCC _zero_reg_ to function properly.
-       ret
+    brne SP_LoadFlashPage_1  ; Repeat until word cont is zero.
+    clr r1                   ; Clear R1 for GCC _zero_reg_ to function properly.
+    ret
 
 
-
-; ---
-; This routine reads an entire Flash page from address R23:R22:R21:R20 into the
-; SRAM buffer at address R25:R24.
-;
-;
-; Input:
-;     R23:R22:R21:R20 - Flash byte address.
-;     R25:R24 - 16-bit pointer to SRAM buffer.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
-.global SP_ReadFlashPage
-
-SP_ReadFlashPage:
-
-       in      r19, RAMPZ                   ; Save RAMPZ during assembly.
-       out     RAMPZ, r22                   ; Load RAMPZ with MSB of address
-       movw    ZL, r20                      ; Load Z with Flash address.
-
-       out     RAMPX, r1                    ; Load RAMPX with data pointer
-       movw    XL, r24                      ; Load X with data buffer address.
-
-       ldi     r20, NVM_CMD_NO_OPERATION_gc ; Prepare NVM command code in R20.
-       sts     NVM_CMD, r20                 ; Set NVM command to No Operation so that LPM reads Flash.
-
-#if APP_SECTION_PAGE_SIZE > 512
-       ldi     r22, ((APP_SECTION_PAGE_SIZE/2) >> 8) ; Load R22 with byte cont high if flash page is large.
-#endif 
-
-       ldi     r21, ((APP_SECTION_PAGE_SIZE)&0xFF)   ; Load R21 with byte count.
-
-SP_ReadFlashPage_1:
-       elpm    r24, Z+                         ; Load Flash bytes into R18:r19
-       elpm    r25, Z+
-       st      X+, r24                         ; Write bytes to buffer.
-       st      X+, r25
-
-#if APP_SECTION_PAGE_SIZE > 512
-       subi    r21, 1                          ; Decrement word count.
-       sbci    r22, 0
-#else
-       dec     r21                             ; Decrement word count.
-#endif 
-
-       brne    SP_ReadFlashPage_1              ; Repeat until byte count is zero.
-
-       out     RAMPZ, r19
-       ret
-
-
-
-; ---
-; This routine writes the page buffer to the Flash page at address R25:R24:R23:R22
+; Writes the page buffer to Flash at address R25:R24:R23:R22
 ; in the application section. The address can point anywhere inside the page.
 ;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
+; Input: R25:R24:R23:R22 - Byte address into Flash page.
+.section .text
 .global SP_WriteApplicationPage
 
 SP_WriteApplicationPage:
-       in      r19, RAMPZ                       ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                       ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                         ; Move low bytes of address to ZH:ZL from R23:R22
-       ldi     r20, NVM_CMD_WRITE_APP_PAGE_gc   ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                     ; Jump to common SPM code.
+    in   r19, RAMPZ            ; Save RAMPZ, restored in SP_CommonSPM.
+    out  RAMPZ, r24            ; Load RAMPZ with the MSB of the address.
+    movw r24, r22              ; Move low bytes of address to ZH:ZL from R23:R22
+    ldi  r20, NVM_CMD_WRITE_APP_PAGE_gc   ; Prepare NVM command in R20.
+    jmp  SP_CommonSPM                     ; Jump to common SPM code.
 
 
-
-; ---
-; This routine erases first and then writes the page buffer to the
+; Erases first and then writes the page buffer to the
 ; Flash page at address R25:R24:R23:R22 in the application section. The address
 ; can point anywhere inside the page.
 ;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
+; Input: R25:R24:R23:R22 - Byte address into Flash page.
 .section .text
 .global SP_EraseWriteApplicationPage
 
 SP_EraseWriteApplicationPage:
-       in      r19, RAMPZ                            ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                            ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                              ; Move low bytes of address to ZH:ZL from R23:R22
-       ldi     r20, NVM_CMD_ERASE_WRITE_APP_PAGE_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                          ; Jump to common SPM code.
-
-
-
-; ---
-; This routine flushes the Flash page buffer.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
-.global SP_EraseFlashBuffer
-
-SP_EraseFlashBuffer:
-       in      r19, RAMPZ                          ; Save RAMPZ, which is restored in SP_CommonSPM.
-       ldi     r20, NVM_CMD_ERASE_FLASH_BUFFER_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                        ; Jump to common SPM code.
-
-
-
-; ---
-; This routine erases the page at address R25:R24:R23:R22 in the Boot section. The
-; address can point anywhere inside the page.
-;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
-.global SP_EraseBootPage
+    in   r19, RAMPZ            ; Save RAMPZ, restored in SP_CommonSPM.
+    out  RAMPZ, r24            ; Load RAMPZ with the MSB of the address.
+    movw r24, r22              ; Move low bytes of address to ZH:ZL from R23:R22
+    ldi  r20, NVM_CMD_ERASE_WRITE_APP_PAGE_gc  ; Prepare NVM command in R20.
+    jmp  SP_CommonSPM                          ; Jump to common SPM code.
 
-SP_EraseBootPage:
-       in      r19, RAMPZ                         ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                         ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                           ; Move low bytes of address to ZH:ZL from R23:R22
-       ldi     r20, NVM_CMD_ERASE_BOOT_PAGE_gc    ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                       ; Jump to common SPM code.
 
 
-
-; ---
-; This routine writes the page buffer to the Flash page at address R25:R24:R23:R22
-; in the BOOT section. The address can point anywhere inside the page.
-;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
-.global SP_WriteBootPage
-
-SP_WriteBootPage:
-       in      r19, RAMPZ                       ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                       ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                         ; Move low bytes of address to ZH:ZL from R23:R22
-       ldi     r20, NVM_CMD_WRITE_BOOT_PAGE_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                     ; Jump to common SPM code.
-
-
-
-; ---
-; This routine erases first and then writes the page buffer to the
-; Flash page at address R25:R24:R23:R22 in the Boot section. The address
-; can point anywhere inside the page.
-;
-; Input:
-;     R25:R24:R23:R22 - Byte address into Flash page.
-;
-; Returns:
-;     Nothing.
-; ---
-
-.section .text         
-.global SP_EraseWriteBootPage
-
-SP_EraseWriteBootPage:
-       in      r19, RAMPZ                             ; Save RAMPZ, which is restored in SP_CommonSPM.
-       out     RAMPZ, r24                             ; Load RAMPZ with the MSB of the address.
-       movw    r24, r22                               ; Move low bytes of address to ZH:ZL from R23:R22
-       ldi     r20, NVM_CMD_ERASE_WRITE_BOOT_PAGE_gc  ; Prepare NVM command in R20.
-       jmp     SP_CommonSPM                           ; Jump to common SPM code.
-
-
-
-; ---
-; This routine calculates a CRC for the application section.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     R25:R24:R23:R22 - 32-bit CRC result (actually only 24-bit used).
-; ---
-
-.section .text 
-.global SP_ApplicationCRC
-
-SP_ApplicationCRC:
-       ldi     r20, NVM_CMD_APP_CRC_gc    ; Prepare NVM command in R20.
-       rjmp    SP_CommonCMD               ; Jump to common NVM Action code.
-
-
-
-; ---
-; This routine calculates a CRC for the Boot section.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     R25:R24:R23:R22 - 32-bit CRC result (actually only 24-bit used).
-; ---
-
-.section .text
-.global SP_BootCRC
-
-SP_BootCRC:
-       ldi     r20, NVM_CMD_BOOT_CRC_gc   ; Prepare NVM command in R20.
-       rjmp    SP_CommonCMD               ; Jump to common NVM Action code.
-
-
-
-; ---
-; This routine locks all further access to SPM operations until next reset.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
-
+; Locks all further access to SPM operations until next reset.
 .section .text
 .global SP_LockSPM
 
 SP_LockSPM:
-       ldi     r18, CCP_IOREG_gc     ; Prepare Protect IO-register signature in R18.
-       sts     CCP, r18              ; Enable IO-register operation (this disables interrupts for 4 cycles).
-       ldi     r18, NVM_SPMLOCK_bm   ; Prepare bitmask for locking SPM into R18.
-       sts     NVM_CTRLB, r18        ; Load bitmask into NVM Control Register B, which locks SPM.
-       ret
-       
+    ldi r18, CCP_IOREG_gc     ; Prepare Protect IO-register signature in R18.
+    sts CCP, r18              ; Enable IO-register operation
+                              ; (disables interrupts for 4 cycles).
+    ldi r18, NVM_SPMLOCK_bm   ; Prepare bitmask for locking SPM into R18.
+    sts NVM_CTRLB, r18        ; Load bitmask into NVM Control Register B,
+                              ; which locks SPM.
+    ret
 
 
-; ---
-; This routine wait for the SPM to finish and clears the command register.
+; Wait for the SPM to finish and clears the command register.
 ;
 ; Note that this routine is blocking, and will halt any execution until the SPM
 ; is finished.
-;
-; Input:
-;     Nothing.
-;
-; Returns:
-;     Nothing.
-; ---
-
 .section .text
-.global SP_WaitForSPM          
+.global SP_WaitForSPM
 
 SP_WaitForSPM:
-       lds     r18, NVM_STATUS     ; Load the NVM Status register.
-       sbrc    r18, NVM_NVMBUSY_bp ; Check if bit is cleared.
-       rjmp    SP_WaitForSPM       ; Repeat check if bit is not cleared.
-       clr     r18
-       sts     NVM_CMD, r18        ; Clear up command register to NO_OPERATION.
-       ret
+    lds  r18, NVM_STATUS     ; Load the NVM Status register.
+    sbrc r18, NVM_NVMBUSY_bp ; Check if bit is cleared.
+    rjmp SP_WaitForSPM       ; Repeat check if bit is not cleared.
+    clr  r18
+    sts  NVM_CMD, r18        ; Clear up command register to NO_OPERATION.
+    ret
 
 
-
-; ---
-; This routine is called by several other routines, and contains common code
+; Called by several other routines, and contains common code
 ; for executing an NVM command, including the return statement itself.
 ;
 ; If the operation (NVM command) requires the NVM Address registers to be
@@ -710,31 +337,27 @@ SP_WaitForSPM:
 ; Note that R25:R24:R23:R22 is used for returning results, even if the
 ; C-domain calling function only expects a single byte or even void.
 ;
-; Input:
-;     R20 - NVM Command code.
-;
-; Returns:
-;     R25:R24:R23:R22 - 32-bit result from NVM operation.
-; ---
-
-.section .text         
+; Input: R20 - NVM Command code.
+; Returns: R25:R24:R23:R22 - 32-bit result from NVM operation.
+.section .text
 
 SP_CommonCMD:
-       sts     NVM_CMD, r20        ; Load command into NVM Command register.
-       ldi     r18, CCP_IOREG_gc   ; Prepare Protect IO-register signature in R18.
-       ldi     r19, NVM_CMDEX_bm   ; Prepare bitmask for setting NVM Command Execute bit into R19.
-       sts     CCP, r18            ; Enable IO-register operation (this disables interrupts for 4 cycles).
-       sts     NVM_CTRLA, r19      ; Load bitmask into NVM Control Register A, which executes the command.
-       lds     r22, NVM_DATA0      ; Load NVM Data Register 0 into R22.
-       lds     r23, NVM_DATA1      ; Load NVM Data Register 1 into R23.
-       lds     r24, NVM_DATA2      ; Load NVM Data Register 2 into R24.
-       clr     r25                 ; Clear R25 in order to return a clean 32-bit value.
-       ret
-
-
-
-; ---
-; This routine is called by several other routines, and contains common code
+    sts NVM_CMD, r20        ; Load command into NVM Command register.
+    ldi r18, CCP_IOREG_gc   ; Prepare Protect IO-register signature in R18.
+    ldi r19, NVM_CMDEX_bm   ; Prepare bitmask for setting NVM Command Execute
+                            ; bit into R19.
+    sts CCP, r18            ; Enable IO-register operation
+                            ; (disables interrupts for 4 cycles).
+    sts NVM_CTRLA, r19      ; Load bitmask into NVM Control Register A,
+                            ; which executes the command.
+    lds r22, NVM_DATA0      ; Load NVM Data Register 0 into R22.
+    lds r23, NVM_DATA1      ; Load NVM Data Register 1 into R23.
+    lds r24, NVM_DATA2      ; Load NVM Data Register 2 into R24.
+    clr r25                 ; Clear R25 in order to return a clean 32-bit value.
+    ret
+
+
+; Called by several other routines, and contains common code
 ; for executing an LPM command, including the return statement itself.
 ;
 ; Note that R24 is used for returning results, even if the
@@ -744,22 +367,17 @@ SP_CommonCMD:
 ;     R25:R24 - Low bytes of Z pointer.
 ;     R20     - NVM Command code.
 ;
-; Returns:
-;     R24     - Result from LPM operation.
-; ---
-
-.section .text         
+; Returns: R24     - Result from LPM operation.
+.section .text
 
 SP_CommonLPM:
-       movw    ZL, r24             ; Load index into Z.
-       sts     NVM_CMD, r20        ; Load prepared command into NVM Command register.
-       lpm     r24,Z
-       ret
-
+    movw ZL, r24             ; Load index into Z.
+    sts  NVM_CMD, r20        ; Load prepared command into NVM Command register.
+    lpm  r24,Z
+    ret
 
 
-; ---
-; This routine is called by several other routines, and contains common code
+; Called by several other routines, and contains common code
 ; for executing an SPM command, including the return statement itself.
 ;
 ; If the operation (SPM command) requires the R1:R0 registers to be
@@ -772,23 +390,14 @@ SP_CommonLPM:
 ;     R1:R0    - Optional input to SPM command.
 ;     R25:R24  - Low bytes of Z pointer.
 ;     R20      - NVM Command code.
-;
-; Returns:
-;     Nothing.
-; ---
-
 .section .text
 
 SP_CommonSPM:
-       movw    ZL, r24          ; Load R25:R24 into Z.
-       sts     NVM_CMD, r20     ; Load prepared command into NVM Command register.
-       ldi     r18, CCP_SPM_gc  ; Prepare Protect SPM signature in R18
-       sts     CCP, r18         ; Enable SPM operation (this disables interrupts for 4 cycles).
-       spm                      ; Self-program.
-       clr     r1               ; Clear R1 for GCC _zero_reg_ to function properly.
-       out     RAMPZ, r19       ; Restore RAMPZ register.
-       ret
-       
-       
-; END OF FILE
-
+    movw ZL, r24         ; Load R25:R24 into Z.
+    sts  NVM_CMD, r20    ; Load prepared command into NVM Command register.
+    ldi  r18, CCP_SPM_gc ; Prepare Protect SPM signature in R18
+    sts  CCP, r18     ; Enable SPM operation (disables interrupts for 4 cycles).
+    spm                  ; Self-program.
+    clr  r1              ; Clear R1 for GCC _zero_reg_ to function properly.
+    out  RAMPZ, r19      ; Restore RAMPZ register.
+    ret
index 0bcbce90c0bd46356e7b1411ca1aff635dde6b11..01aeaee519fc1ae28a2917662777a73704117e84 100644 (file)
@@ -1,36 +1,4 @@
-/* This file has been prepared for Doxygen automatic documentation generation.*/
-/*! \file *********************************************************************
- *
- * \brief  XMEGA Self-programming driver header file.
- *
- *      This file contains the function prototypes for the
- *      XMEGA Self-programming driver.
- *      If any SPM instructions are used, the linker file must define
- *      a segment named BOOT which must be located in the device boot section.
- *
- *
- *      None of these functions clean up the NVM Command Register after use.
- *      It is therefore important to write NVMCMD_NO_OPERATION (0x00) to this
- *      register when you are finished using any of the functions in this
- *      driver.
- *
- *      For all functions, it is important that no interrupt handlers perform
- *      any NVM operations. The user must implement a scheme for mutually
- *      exclusive access to the NVM. However, the 4-cycle timeout will work
- *      fine, since writing to the Configuration Change Protection register
- *      (CCP) automatically disables interrupts for 4 instruction cycles.
- *
- * \par Application note:
- *      AVR1316: XMEGA Self-programming
- *
- * \par Documentation
- *      For comprehensive code documentation, supported compilers, compiler
- *      settings and supported devices see readme.html
- *
- * \author
- *      Atmel Corporation: http://www.atmel.com \n
- *      Support email: avr@atmel.com
- *
+/*******************************************************************************
  * $Revision: 1691 $
  * $Date: 2008-07-29 13:25:40 +0200 (ti, 29 jul 2008) $  \n
  *
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-#ifndef SP_DRIVER_H
-#define SP_DRIVER_H
+ ******************************************************************************/
 
-//#include "avr_compiler.h"
-//#include "Flash_Defines.h"
+/*! \file **********************************************************************
+ * \brief XMEGA Self-programming driver header file.
+ *
+ *      This file contains the function prototypes for the
+ *      XMEGA Self-programming driver.
+ *      If any SPM instructions are used, the linker file must define
+ *      a segment named BOOT which must be located in the device boot section.
+ *
+ *
+ *      None of these functions clean up the NVM Command Register after use.
+ *      It is therefore important to write NVMCMD_NO_OPERATION (0x00) to this
+ *      register when you are finished using any of the functions in this
+ *      driver.
+ *
+ *      For all functions, it is important that no interrupt handlers perform
+ *      any NVM operations. The user must implement a scheme for mutually
+ *      exclusive access to the NVM. However, the 4-cycle timeout will work
+ *      fine, since writing to the Configuration Change Protection register
+ *      (CCP) automatically disables interrupts for 4 instruction cycles.
+ *
+ * \par Application note: AVR1316: XMEGA Self-programming
+ *
+ * \par Documentation
+ *      For comprehensive code documentation, supported compilers, compiler
+ *      settings and supported devices see readme.html
+ *
+ * \author
+ *      Atmel Corporation: http://www.atmel.com
+ *      Support email: avr@atmel.com
+ ******************************************************************************/
 
+#pragma once
 
+#include <avr/io.h>
+
+#include <stdint.h>
 
-/* Define the size of the flash page if not defined in the header files. */
 #ifndef APP_SECTION_PAGE_SIZE
-#error  APP_SECTION_PAGE_SIZE must be defined if not defined in header files.
-//#define APP_SECTION_PAGE_SIZE 512
-#endif /*FLASH_PAGE_SIZE*/
+#error APP_SECTION_PAGE_SIZE must be defined if not defined in header files.
+#endif
 
-// Define the Start of the application table if not defined in the header files.
 #ifndef APPTABLE_SECTION_START
-#error  APPTABLE_SECTION_START must be defined if not defined in header files.
-//#define APPTABLE_SECTION_START 0x01E000 //APPTABLE address for ATxmega128A1
-#endif /*APPTABLE_SECTION_START*/
+#error APPTABLE_SECTION_START must be defined if not defined in header files.
+#endif
+
 
 /*! \brief Read a byte from flash.
- *
- *  This function reads one byte from the flash.
- *
- *  \note Both IAR and GCC have functions to do this, but
- *        we include the fucntions for easier use.
  *
  *  \param address Address to the location of the byte to read.
- *
  *  \retval Byte read from flash.
  */
 uint8_t SP_ReadByte(uint32_t address);
@@ -97,9 +86,6 @@ uint8_t SP_ReadByte(uint32_t address);
  *
  *  This function reads one word from the flash.
  *
- *  \note Both IAR and GCC have functions to do this automatically, but
- *        we include the fucntions for easier use.
- *
  *  \param address Address to the location of the word to read.
  *
  *  \retval word read from flash.
@@ -121,76 +107,33 @@ uint8_t SP_ReadCalibrationByte(uint8_t index);
  *  This function reads the fuse byte at the given index.
  *
  *  \param index  Index of the fuse byte.
- *
  *  \retval Fuse byte
  */
 uint8_t SP_ReadFuseByte(uint8_t index);
 
-/*! \brief Write lock bits.
- *
- *  This function changes the lock bits.
- *
- *  \note It is only possible to change the lock bits to a higher security l
- *  evel.
- *
- *  \param data  The new value of the lock bits.
- */
-void SP_WriteLockBits(uint8_t data);
-
-/*! \brief Read lock bits.
- *
- *  This function reads the lock bits.
- *
- *  \retval Lock bits
- */
-uint8_t SP_ReadLockBits(void);
-
 /*! \brief Read user signature at given index.
- *
- *  This function reads one byte from the user signature row.
  *
  *  \param index  Index of the byte in the user signature row.
- *
  *  \retval User signature byte
  */
 uint8_t SP_ReadUserSignatureByte(uint16_t index);
 
-/*! \brief Erase user signature row.
- *
- *  This function erase the entire user signature row.
- */
-void SP_EraseUserSignatureRow(void);
+/// Erase user signature row.
+void SP_EraseUserSignatureRow();
 
-/*! \brief Write user signature row.
- *
- *  This function write the flash buffer in the user signature row.
- */
-void SP_WriteUserSignatureRow(void);
+/// Write user signature row.
+void SP_WriteUserSignatureRow();
 
 /*! \brief Erase entire application section.
  *
- *  This function erases the entire application and application table section
- *
- *  \note If the lock bits is set to not allow spm in the application or
+ *  \note If the lock bits is set to not allow SPM in the application or
  *        application table section the erase is not done.
  */
-void SP_EraseApplicationSection(void);
-
-/*! \brief Erase page at byte address in application or application table
- * section.
- *
- *  This function erase one page given by the byte address.
- *
- *  \param address Byte address for flash page.
- */
-void SP_EraseApplicationPage(uint32_t address);
+void SP_EraseApplicationSection();
 
 /*! \brief Erase and write page buffer to application or application table
  *  section at byte address.
  *
- *  This function does a combined erase and write to a flash page in the
- *  application or application table section.
- *
  *  \param address Byte address for flash page.
  */
 void SP_EraseWriteApplicationPage(uint32_t address);
@@ -198,9 +141,6 @@ void SP_EraseWriteApplicationPage(uint32_t address);
 /*! \brief Write page buffer to application or application table section at
  *  byte address.
  *
- *  This function writes the Flash page buffer to a page in the application or
- *  application table section given by the byte address.
- *
  *  \note The page that is written to must be erased before it is written to.
  *
  *  \param address Byte address for flash page.
@@ -208,8 +148,6 @@ void SP_EraseWriteApplicationPage(uint32_t address);
 void SP_WriteApplicationPage(uint32_t address);
 
 /*! \brief Load one word into Flash page buffer.
- *
- *  This function Loads one word into the Flash page buffer.
  *
  *  \param  address   Position in inside the flash page buffer.
  *  \param  data      Value to be put into the buffer.
@@ -217,82 +155,19 @@ void SP_WriteApplicationPage(uint32_t address);
 void SP_LoadFlashWord(uint16_t address, uint16_t data);
 
 /*! \brief Load entire page from SRAM buffer into Flash page buffer.
- *
- *  This function load an entire page from SRAM.
  *
  *     \param data   Pointer to the data to put in buffer.
  *
  *     \note The __near keyword limits the pointer to two bytes which means that
  *        only data up to 64K (internal SRAM) can be used.
  */
-void SP_LoadFlashPage(const uint8_t * data);
+void SP_LoadFlashPage(const uint8_t *data);
 
-/*! \brief Read entire Flash page into SRAM buffer.
- *
- *  This function reads an entire flash page and puts it to SRAM.
- *
- *     \param data      Pointer to where to store the data.
- *     \param address   Address to page to read from flash.
- */
-void SP_ReadFlashPage(const uint8_t * data, uint32_t address);
+/// Flush Flash page buffer.
+void SP_EraseFlashBuffer();
 
-/*! \brief Flush Flash page buffer.
- *
- *  This function flush the Flash page buffer.
- */
-void SP_EraseFlashBuffer(void);
-
-/*! \brief Erase page at byte address in boot section.
- *
- *  This function erase one page given by the byte address.
- *
- *  \param address Byte address for flash page.
- */
-void SP_EraseBootPage(uint32_t address);
-
-/*! \brief Erase and write page buffer to boot section at byte address.
- *
- *  This function does a combined erase and write to a flash page in the boot
- *  section.
- *
- *  \param address Byte address for flash page.
- */
-void SP_EraseWriteBootPage(uint32_t address);
-
-/*! \brief Write page buffer to boot section at byte address.
- *
- *  This function writes the Flash page buffer to a page in the boot section
- *  given by the byte address.
- *
- *  \note The page that is written to must be erased before it is written to.
- *
- *  \param address Byte address for flash page.
- */
-void SP_WriteBootPage(uint32_t address);
-
-/*! \brief Generate CRC from application section.
- *
- *  \retval 24-bit CRC value
- */
-uint32_t SP_ApplicationCRC(void);
-
-/*! \brief Generate CRC from boot section.
- *
- *  \retval 24-bit CRC value
- */
-uint32_t SP_BootCRC(void);
-
-/*! \brief Lock SPM instruction.
- *
- *   This function locks the SPM instruction, and will disable the use of
- *   SPM until the next reset occurs.
- */
-void SP_LockSPM(void);
-
-/*! \brief Wait for SPM to finish.
- *
- *   This routine waits for the SPM to finish and clears the command register.
- */
-void SP_WaitForSPM(void);
+/// Disables the use of SPM until the next reset.
+void SP_LockSPM();
 
-#endif /* SP_DRIVER_H */
+/// Waits for the SPM to finish and clears the command register.
+void SP_WaitForSPM();
diff --git a/avr/src/xboot/uart.c b/avr/src/xboot/uart.c
deleted file mode 100644 (file)
index c4cf091..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* UART Module                                                          */
-/*                                                                      */
-/* uart.c                                                               */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#include "uart.h"
-#include "xboot.h"
-
-
-bool uart_has_char() {return UART_DEVICE.STATUS & USART_RXCIF_bm;}
-uint8_t uart_recv_char() {return UART_DEVICE.DATA;}
-
-
-void uart_send_char_blocking(uint8_t c) {
-  UART_DEVICE.DATA = c;
-  while (!(UART_DEVICE.STATUS & USART_TXCIF_bm)) continue;
-  UART_DEVICE.STATUS |= USART_TXCIF_bm;
-}
-
-
-void uart_init() {
-  UART_PORT.DIRSET = 1 << UART_TX_PIN;
-  UART_DEVICE.BAUDCTRLA = UART_BSEL_VALUE & USART_BSEL_gm;
-  UART_DEVICE.BAUDCTRLB =
-    ((UART_BSCALE_VALUE << USART_BSCALE_gp) & USART_BSCALE_gm) |
-    ((UART_BSEL_VALUE >> 8) & ~USART_BSCALE_gm);
-
-#if UART_CLK2X
-  UART_DEVICE.CTRLB = USART_RXEN_bm | USART_CLK2X_bm | USART_TXEN_bm;
-#else
-  UART_DEVICE.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
-#endif // UART_CLK2X
-
-  PORTC.OUTCLR = 1 << 4; // CTS Lo (enable)
-  PORTC.DIRSET = 1 << 4; // CTS Output
-}
-
-
-void uart_deinit() {
-  UART_DEVICE.CTRLB = 0;
-  UART_DEVICE.BAUDCTRLA = 0;
-  UART_DEVICE.BAUDCTRLB = 0;
-  UART_PORT.DIRCLR = 1 << UART_TX_PIN;
-}
diff --git a/avr/src/xboot/uart.h b/avr/src/xboot/uart.h
deleted file mode 100644 (file)
index 0392f7e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* UART Module                                                          */
-/*                                                                      */
-/* uart.h                                                               */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#pragma once
-
-#include <stdbool.h>
-#include <stdint.h>
-
-bool uart_has_char();
-uint8_t uart_recv_char();
-void uart_send_char_blocking(uint8_t c);
-void uart_init(void);
-void uart_deinit(void);
diff --git a/avr/src/xboot/watchdog.c b/avr/src/xboot/watchdog.c
deleted file mode 100644 (file)
index a7e1064..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* Watchdog Module                                                      */
-/*                                                                      */
-/* watchdog.c                                                           */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#include "watchdog.h"
-
-
-void WDT_EnableAndSetTimeout() {
-  uint8_t temp = WDT_ENABLE_bm | WDT_CEN_bm | WATCHDOG_TIMEOUT;
-  CCP = CCP_IOREG_gc;
-  WDT.CTRL = temp;
-
-  // Wait for WD to synchronize with new settings.
-  while (WDT_IsSyncBusy()) continue;
-}
-
-
-void WDT_Disable() {
-  uint8_t temp = (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm;
-  CCP = CCP_IOREG_gc;
-  WDT.CTRL = temp;
-}
diff --git a/avr/src/xboot/watchdog.h b/avr/src/xboot/watchdog.h
deleted file mode 100644 (file)
index f9fcc74..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* Watchdog Module                                                      */
-/*                                                                      */
-/* watchdog.c                                                           */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
-
-#pragma once
-
-#include "xboot.h"
-
-#define WDT_IsSyncBusy() (WDT.STATUS & WDT_SYNCBUSY_bm)
-#define WDT_Reset() asm("wdr")
-
-void WDT_EnableAndSetTimeout();
-void WDT_Disable();
index 7fd5ac0fe21748ee48550d8995f59b644ec886b9..03bbc32dc5b0dbb3debd4e52adba72812429f703 100644 (file)
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* xboot.c                                                              */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+          Copyright (c) 2010 Alex Forencich <alex@alexforencich.com>
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software is distributed in the hope that it will be useful, but
+          WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+               Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
 
 #include "xboot.h"
+#include "sp_driver.h"
 
 #include <util/delay.h>
+#include <util/crc16.h>
+
+#include <avr/eeprom.h>
+#include <avr/io.h>
 
 #include <stdbool.h>
 
 
 uint8_t buffer[SPM_PAGESIZE];
+uint16_t block_crc = 0;
+
+
+void clock_init() {
+  // External 16Mhz Xtal w/ 2x PLL = 32 Mhz
+  // 12-16 MHz crystal; 0.4-16 MHz XTAL w/ 16K CLK startup
+  OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
+  OSC.CTRL = OSC_XOSCEN_bm;                // enable external crystal oscillator
+  while (!(OSC.STATUS & OSC_XOSCRDY_bm));  // wait for oscillator ready
 
+  OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2;    // PLL source, 2x (32 MHz sys clock)
+  OSC.CTRL = OSC_PLLEN_bm | OSC_XOSCEN_bm; // Enable PLL & External Oscillator
+  while (!(OSC.STATUS & OSC_PLLRDY_bm));   // wait for PLL ready
 
-void NVM_Wait() {
-  while (NVM_STATUS & NVM_NVMBUSY_bp)
-    // reset watchdog while waiting for erase completion
-    WDT_Reset();
+  CCP = CCP_IOREG_gc;
+  CLK.CTRL = CLK_SCLKSEL_PLL_gc;           // switch to PLL clock
+  OSC.CTRL &= ~OSC_RC2MEN_bm;              // disable internal 2 MHz clock
 }
 
 
-int main() {
-  // Initialization section
-  // Entry point and communication methods are initialized here
-  // --------------------------------------------------
-#ifdef USE_32MHZ_RC
-#if (F_CPU != 32000000L)
-#error F_CPU must match oscillator setting!
-#endif // F_CPU
-  OSC.CTRL |= OSC_RC32MEN_bm; // turn on 32 MHz oscillator
-  while (!(OSC.STATUS & OSC_RC32MRDY_bm)) continue; // wait for it to start
+bool uart_has_char() {return UART_DEVICE.STATUS & USART_RXCIF_bm;}
+uint8_t uart_recv_char() {return UART_DEVICE.DATA;}
+
+
+void uart_send_char_blocking(uint8_t c) {
+  UART_DEVICE.DATA = c;
+  while (!(UART_DEVICE.STATUS & USART_TXCIF_bm)) continue;
+  UART_DEVICE.STATUS |= USART_TXCIF_bm;
+}
+
+
+void uart_init() {
+  UART_PORT.DIRSET = 1 << UART_TX_PIN;
+  UART_DEVICE.BAUDCTRLA = UART_BSEL_VALUE & USART_BSEL_gm;
+  UART_DEVICE.BAUDCTRLB =
+    ((UART_BSCALE_VALUE << USART_BSCALE_gp) & USART_BSCALE_gm) |
+    ((UART_BSEL_VALUE >> 8) & ~USART_BSCALE_gm);
+  UART_DEVICE.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
+
+  PORTC.OUTCLR = 1 << 4; // CTS Lo (enable)
+  PORTC.DIRSET = 1 << 4; // CTS Output
+}
+
+
+void uart_deinit() {
+  UART_DEVICE.CTRLB = 0;
+  UART_DEVICE.BAUDCTRLA = 0;
+  UART_DEVICE.BAUDCTRLB = 0;
+  UART_PORT.DIRCLR = 1 << UART_TX_PIN;
+}
+
+
+void watchdog_init() {
+  uint8_t temp = WDT_ENABLE_bm | WDT_CEN_bm | WDT_PER_1KCLK_gc;
   CCP = CCP_IOREG_gc;
-  CLK.CTRL = CLK_SCLKSEL_RC32M_gc;
-#ifdef USE_DFLL
-  OSC.CTRL |= OSC_RC32KEN_bm;
-  while(!(OSC.STATUS & OSC_RC32KRDY_bm));
-  DFLLRC32M.CTRL = DFLL_ENABLE_bm;
-#endif // USE_DFLL
-#else // USE_32MHZ_RC
-#if (F_CPU != 2000000L)
-#error F_CPU must match oscillator setting!
-#endif // F_CPU
-#ifdef USE_DFLL
-  OSC.CTRL |= OSC_RC32KEN_bm;
-  while(!(OSC.STATUS & OSC_RC32KRDY_bm));
-  DFLLRC2M.CTRL = DFLL_ENABLE_bm;
-#endif // USE_DFLL
-#endif // USE_32MHZ_RC
-
-  // Initialize UART
-  uart_init();
+  WDT.CTRL = temp;
+  while (WDT.STATUS & WDT_SYNCBUSY_bm) continue;
+}
 
-  // End initialization section
 
-  uint32_t address = 0;
-  uint16_t i = 0;
+void watchdog_reset() {asm("wdr");}
+
+
+void watchdog_disable() {
+  uint8_t temp = (WDT.CTRL & ~WDT_ENABLE_bm) | WDT_CEN_bm;
+  CCP = CCP_IOREG_gc;
+  WDT.CTRL = temp;
+}
+
+
+void nvm_wait() {while (NVM_STATUS & NVM_NVMBUSY_bp) watchdog_reset();}
+
+
+void nvm_exec() {
+  void *z = (void *)&NVM_CTRLA;
+
+  __asm__ volatile
+    ("out %[ccp], %[ioreg]\n"
+     "st z, %[cmdex]" ::
+     [ccp] "I" (_SFR_IO_ADDR(CCP)),
+     [ioreg] "d" (CCP_IOREG_gc),
+     [cmdex] "r" (NVM_CMDEX_bm),
+     [z] "z" (z));
+}
+
 
+uint8_t get_char() {
+  while (!uart_has_char()) continue;
+  return uart_recv_char();
+}
+
+
+void send_char(uint8_t c) {uart_send_char_blocking(c);}
+
+
+uint16_t get_word() {
+  uint8_t hi = get_char();
+  uint8_t lo = get_char();
+  return ((uint16_t)hi << 8) | lo;
+}
+
+
+uint8_t BlockLoad(unsigned size, uint8_t mem, uint32_t *address) {
+  watchdog_reset();
+
+  // fill up buffer
+  block_crc = 0xffff;
+  for (int i = 0; i < SPM_PAGESIZE; i++)
+    if (i < size) {
+      buffer[i] = get_char();
+      block_crc = _crc16_update(block_crc, buffer[i]);
+
+    } else buffer[i] = 0xff;
+
+  switch (mem) {
+  case MEM_EEPROM:
+    eeprom_write_block(buffer, (uint8_t *)(uint16_t)*address, size);
+    *address += size;
+    break;
+
+  case MEM_FLASH:
+    // NOTE: Flash programming, address is given in words.
+    SP_LoadFlashPage(buffer);
+    SP_EraseWriteApplicationPage(*address << 1);
+    *address += size >> 1;
+    nvm_wait();
+    break;
+
+  case MEM_USERSIG:
+    SP_LoadFlashPage(buffer);
+    SP_EraseUserSignatureRow();
+    nvm_wait();
+    SP_WriteUserSignatureRow();
+    nvm_wait();
+    break;
+
+  default: return REPLY_ERROR;
+  }
+
+  return REPLY_ACK;
+}
+
+
+
+void BlockRead(unsigned size, uint8_t mem, uint32_t *address) {
+  switch (mem) {
+  case MEM_EEPROM:
+    eeprom_read_block(buffer, (uint8_t *)(uint16_t)*address, size);
+    *address += size;
+
+    // send bytes
+    for (int i = 0; i < size; i++)
+      send_char(buffer[i]);
+    break;
+
+  case MEM_FLASH: case MEM_USERSIG: case MEM_PRODSIG: {
+    *address <<= 1; // Convert address to bytes temporarily
+
+    do {
+      switch (mem) {
+      case MEM_FLASH: send_char(SP_ReadByte(*address)); break;
+      case MEM_USERSIG: send_char(SP_ReadUserSignatureByte(*address)); break;
+      case MEM_PRODSIG: send_char(SP_ReadCalibrationByte(*address)); break;
+      }
+
+      nvm_wait();
+
+      (*address)++;    // Select next word in memory.
+      size--;          // Subtract two bytes from number of bytes to read
+    } while (size);    // Repeat until all block has been read
+
+    *address >>= 1;    // Convert address back to Flash words again.
+    break;
+  }
+
+  default: break;
+  }
+}
+
+
+int main() {
+  // Init
+  clock_init();
+  uart_init();
+  watchdog_init();
+
+  // Check for trigger
   bool in_bootloader = false;
-  uint16_t j = ENTER_WAIT;
+  uint16_t j = INITIAL_WAIT;
   while (!in_bootloader && 0 < j--) {
-    // Check for trigger
     if (uart_has_char()) in_bootloader = uart_recv_char() == CMD_SYNC;
-
+    watchdog_reset();
     _delay_ms(1);
   }
 
-  WDT_EnableAndSetTimeout();
-
   // Main bootloader
+  uint32_t address = 0;
+  uint16_t i = 0;
+
   while (in_bootloader) {
     uint8_t val = get_char();
-    WDT_Reset();
+    watchdog_reset();
 
     // Main bootloader parser
     switch (val) {
@@ -107,20 +251,23 @@ int main() {
       send_char(REPLY_ACK);
       break;
 
-    case CMD_SET_EXT_ADDRESS:
-      address = ((uint32_t)get_char() << 16) | get_word();
+    case CMD_SET_EXT_ADDRESS: {
+      uint8_t hi = get_char();
+      address = ((uint32_t)hi << 16) | get_word();
       send_char(REPLY_ACK);
       break;
+    }
 
     case CMD_CHIP_ERASE:
       // Erase the application section
       SP_EraseApplicationSection();
 
       // Wait for completion
-      NVM_Wait();
+      nvm_wait();
 
       // Erase EEPROM
-      EEPROM_erase_all();
+      NVM.CMD = NVM_CMD_ERASE_EEPROM_gc;
+      nvm_exec();
 
       send_char(REPLY_ACK);
       break;
@@ -128,8 +275,8 @@ int main() {
     case CMD_CHECK_BLOCK_SUPPORT:
       send_char(REPLY_YES);
       // Send block size (page size)
-      send_char((SPM_PAGESIZE >> 8) & 0xFF);
-      send_char(SPM_PAGESIZE & 0xFF);
+      send_char(SPM_PAGESIZE >> 8);
+      send_char((uint8_t)SPM_PAGESIZE);
       break;
 
     case CMD_BLOCK_LOAD:
@@ -145,7 +292,7 @@ int main() {
       break;
 
     case CMD_READ_BYTE: {
-      unsigned w = SP_ReadWord((address << 1));
+      unsigned w = SP_ReadWord(address << 1);
 
       send_char(w >> 8);
       send_char(w);
@@ -161,7 +308,7 @@ int main() {
 
     case CMD_WRITE_HIGH_BYTE:
       i |= (get_char() << 8); // get high byte; combine
-      SP_LoadFlashWord((address << 1), i);
+      SP_LoadFlashWord(address << 1, i);
       address++;
       send_char(REPLY_ACK);
       break;
@@ -177,13 +324,13 @@ int main() {
       break;
 
     case CMD_WRITE_EEPROM_BYTE:
-      EEPROM_write_byte(address, get_char());
+      eeprom_write_byte((uint8_t *)(uint16_t)address, get_char());
       address++;
       send_char(REPLY_ACK);
       break;
 
     case CMD_READ_EEPROM_BYTE:
-      send_char(EEPROM_read_byte(address));
+      send_char(eeprom_read_byte((uint8_t *)(uint16_t)address));
       address++;
       break;
 
@@ -213,18 +360,18 @@ int main() {
       break;
 
     case CMD_PROGRAM_ID:
-      send_char('X');
-      send_char('B');
-      send_char('o');
-      send_char('o');
+      send_char('b');
+      send_char('b');
+      send_char('c');
       send_char('t');
-      send_char('+');
-      send_char('+');
+      send_char('r');
+      send_char('l');
+      send_char(' ');
       break;
 
     case CMD_VERSION:
-      send_char('0' + XBOOT_VERSION_MAJOR);
-      send_char('0' + XBOOT_VERSION_MINOR);
+      send_char('0');
+      send_char('1');
       break;
 
     case CMD_READ_SIGNATURE:
@@ -233,32 +380,10 @@ int main() {
       send_char(SIGNATURE_0);
       break;
 
-    case CMD_CRC: {
-      uint32_t start = 0;
-      uint32_t length = 0;
-      uint16_t crc;
-
-      val = get_char();
-
-      switch (val) {
-      case SECTION_FLASH: length = PROGMEM_SIZE; break;
-      case SECTION_APPLICATION: length = APP_SECTION_SIZE; break;
-      case SECTION_BOOT:
-        start = BOOT_SECTION_START;
-        length = BOOT_SECTION_SIZE;
-        break;
-
-      default:
-        send_char(REPLY_ERROR);
-        continue;
-      }
-
-      crc = crc16_block(start, length);
-
-      send_char((crc >> 8) & 0xff);
-      send_char(crc & 0xff);
+    case CMD_BLOCK_CRC:
+      send_char(block_crc >> 8);
+      send_char((uint8_t)block_crc);
       break;
-    }
 
     case CMD_SYNC: break; // ESC (0x1b) to sync
 
@@ -268,134 +393,16 @@ int main() {
     }
 
     // Wait for any lingering SPM instructions to finish
-    NVM_Wait();
+    nvm_wait();
   }
 
-  // Bootloader exit
-  // Code here runs after the bootloader has exited,
-  // but before the application code has started
-
-  // Shut down UART
+  // Deinit
   uart_deinit();
+  watchdog_disable();
 
-  WDT_Disable();
+  // Disable further self programming until next reset
+  SP_LockSPM();
 
-  // Jump into main code
+  // Jump to application code
   asm("jmp 0");
 }
-
-
-uint8_t get_char() {
-  while (!uart_has_char()) continue;
-  return uart_recv_char();
-}
-
-
-void send_char(uint8_t c) {uart_send_char_blocking(c);}
-uint16_t get_word() {return (get_char() << 8) | get_char();}
-
-
-uint8_t BlockLoad(unsigned size, uint8_t mem, uint32_t *address) {
-  WDT_Reset();
-
-  // fill up buffer
-  for (int i = 0; i < SPM_PAGESIZE; i++) {
-    char c = 0xff;
-    if (i < size) c = get_char();
-    buffer[i] = c;
-  }
-
-  switch (mem) {
-  case MEM_EEPROM:
-    EEPROM_write_block(*address, buffer, size);
-    *address += size;
-    break;
-
-  case MEM_FLASH:
-    // NOTE: Flash programming, address is given in words.
-    SP_LoadFlashPage(buffer);
-    SP_EraseWriteApplicationPage(*address << 1);
-    *address += size >> 1;
-    NVM_Wait();
-    break;
-
-  case MEM_USERSIG:
-    SP_LoadFlashPage(buffer);
-    SP_EraseUserSignatureRow();
-    NVM_Wait();
-    SP_WriteUserSignatureRow();
-    NVM_Wait();
-    break;
-
-  default: return REPLY_ERROR;
-  }
-
-  return REPLY_ACK;
-}
-
-
-
-void BlockRead(unsigned size, uint8_t mem, uint32_t *address) {
-  int offset = 0;
-  int size2 = size;
-
-  switch (mem) {
-  case MEM_EEPROM:
-    EEPROM_read_block(*address, buffer, size);
-    (*address) += size;
-    break;
-
-  case MEM_FLASH: case MEM_USERSIG: case MEM_PRODSIG: {
-    *address <<= 1; // Convert address to bytes temporarily
-
-    do {
-      switch (mem) {
-      case MEM_FLASH: buffer[offset++] = SP_ReadByte(*address); break;
-
-      case MEM_USERSIG:
-        buffer[offset++] = SP_ReadUserSignatureByte(*address);
-        break;
-
-      case MEM_PRODSIG:
-        buffer[offset++] = SP_ReadCalibrationByte(*address);
-        break;
-      }
-
-      NVM_Wait();
-
-      (*address)++;    // Select next word in memory.
-      size--;          // Subtract two bytes from number of bytes to read
-    } while (size);    // Repeat until all block has been read
-
-    *address >>= 1;    // Convert address back to Flash words again.
-    break;
-  }
-
-  default: send_char(REPLY_ERROR); break;
-  }
-
-  // send bytes
-  for (int i = 0; i < size2; i++)
-    send_char(buffer[i]);
-}
-
-
-uint16_t crc16_block(uint32_t start, uint32_t length) {
-  uint16_t crc = 0;
-
-  int bc = SPM_PAGESIZE;
-
-  for (; length > 0; length--) {
-    if (bc == SPM_PAGESIZE) {
-      SP_ReadFlashPage(buffer, start);
-      start += SPM_PAGESIZE;
-      bc = 0;
-    }
-
-    crc = _crc16_update(crc, buffer[bc]);
-
-    bc++;
-  }
-
-  return crc;
-}
index 7b327d766d2fc0dcccd0d8a644a79a01ae1308a9..9b6814207a1f820a886a0491b106912751b62ee3 100644 (file)
-/************************************************************************/
-/* XBoot Extensible AVR Bootloader                                      */
-/*                                                                      */
-/* xboot.h                                                              */
-/*                                                                      */
-/* Alex Forencich <alex@alexforencich.com>                              */
-/*                                                                      */
-/* Copyright (c) 2010 Alex Forencich                                    */
-/*                                                                      */
-/* Permission is hereby granted, free of charge, to any person          */
-/* obtaining a copy of this software and associated documentation       */
-/* files(the "Software"), to deal in the Software without restriction,  */
-/* including without limitation the rights to use, copy, modify, merge, */
-/* publish, distribute, sublicense, and/or sell copies of the Software, */
-/* and to permit persons to whom the Software is furnished to do so,    */
-/* subject to the following conditions:                                 */
-/*                                                                      */
-/* The above copyright notice and this permission notice shall be       */
-/* included in all copies or substantial portions of the Software.      */
-/*                                                                      */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
-/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
-/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
-/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
-/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
-/* SOFTWARE.                                                            */
-/*                                                                      */
-/************************************************************************/
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+          Copyright (c) 2010 Alex Forencich <alex@alexforencich.com>
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software is distributed in the hope that it will be useful, but
+          WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+               Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
 
 #pragma once
 
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include <util/crc16.h>
-
-// token pasting
-#define CAT2_int(x, y) x ## y
-#define CAT2(x, y) CAT2_int(x, y)
-#define CAT3_int(x, y, z) x ## y ## z
-#define CAT3(x, y, z) CAT3_int(x, y, z)
-
-// Version
-#define XBOOT_VERSION_MAJOR 1
-#define XBOOT_VERSION_MINOR 7
-
-// Configuration
-#define ENTER_WAIT 1000 // In ms
-#define UART_BAUD_RATE 115200
-#define UART_NUMBER 0
-#define UART_PORT_NAME C
-#define USE_AVR1008_EEPROM
-#define USE_DFLL
-#define WATCHDOG_TIMEOUT WDT_PER_1KCLK_gc
-
-// clock config
-// use 32MHz osc if makefile calls for it
-#if (F_CPU == 32000000L)
-// defaults to 2MHz RC oscillator
-// define USE_32MHZ_RC to override
-#define USE_32MHZ_RC
-#endif // F_CPU
-
-// UART RS485 Enable Output
-#define UART_EN_PORT            CAT2(PORT, UART_EN_PORT_NAME)
-
-#if (UART_NUMBER == 0)
+#define INITIAL_WAIT 1000 // In ms
+
 #define UART_RX_PIN             2
 #define UART_TX_PIN             3
-#else
-#define UART_RX_PIN             6
-#define UART_TX_PIN             7
-#endif
-#define UART_PORT               CAT2(PORT, UART_PORT_NAME)
-#define UART_DEVICE_PORT        CAT2(UART_PORT_NAME, UART_NUMBER)
-#define UART_DEVICE             CAT2(USART, UART_DEVICE_PORT)
-#define UART_DEVICE_RXC_ISR     CAT3(USART, UART_DEVICE_PORT, _RXC_vect)
-#define UART_DEVICE_DRE_ISR     CAT3(USART, UART_DEVICE_PORT, _DRE_vect)
-#define UART_DEVICE_TXC_ISR     CAT3(USART, UART_DEVICE_PORT, _TXC_vect)
-#define UART_RX_PIN_CTRL        CAT3(UART_PORT.PIN, UART_RX_PIN, CTRL)
-#define UART_TX_PIN_CTRL        CAT3(UART_PORT.PIN, UART_TX_PIN, CTRL)
-
-// BAUD Rate Values
-// Known good at 2MHz
-#if (F_CPU == 2000000L) && (UART_BAUD_RATE == 19200)
-#define UART_BSEL_VALUE         12
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              1
-#elif (F_CPU == 2000000L) && (UART_BAUD_RATE == 38400)
-#define UART_BSEL_VALUE         22
-#define UART_BSCALE_VALUE       -2
-#define UART_CLK2X              1
-#elif (F_CPU == 2000000L) && (UART_BAUD_RATE == 57600)
-#define UART_BSEL_VALUE         26
-#define UART_BSCALE_VALUE       -3
-#define UART_CLK2X              1
-#elif (F_CPU == 2000000L) && (UART_BAUD_RATE == 115200)
-#define UART_BSEL_VALUE         19
-#define UART_BSCALE_VALUE       -4
-#define UART_CLK2X              1
-
-// Known good at 32MHz
-#elif (F_CPU == 32000000L) && (UART_BAUD_RATE == 19200)
-#define UART_BSEL_VALUE         103
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              0
-#elif (F_CPU == 32000000L) && (UART_BAUD_RATE == 38400)
-#define UART_BSEL_VALUE         51
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              0
-#elif (F_CPU == 32000000L) && (UART_BAUD_RATE == 57600)
-#define UART_BSEL_VALUE         34
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              0
-#elif (F_CPU == 32000000L) && (UART_BAUD_RATE == 115200)
+#define UART_PORT               PORTC
+#define UART_DEVICE             USARTC0
+
+// Baud rate 115200 @ 32Mhz
 #define UART_BSEL_VALUE         1047
 #define UART_BSCALE_VALUE       -6
-#define UART_CLK2X              0
-
-#else // None of the above, so calculate something
-#warning Not using predefined BAUD rate, possible BAUD rate error!
-#if (F_CPU == 2000000L)
-#define UART_BSEL_VALUE         ((F_CPU) / ((uint32_t)UART_BAUD_RATE * 8) - 1)
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              1
-
-#else
-#define UART_BSEL_VALUE         ((F_CPU) / ((uint32_t)UART_BAUD_RATE * 16) - 1)
-#define UART_BSCALE_VALUE       0
-#define UART_CLK2X              0
-#endif
-#endif
-
-#ifndef EEPROM_PAGE_SIZE
-#define EEPROM_PAGE_SIZE E2PAGESIZE
-#endif
-
-#ifndef EEPROM_BYTE_ADDRESS_MASK
-#if EEPROM_PAGE_SIZE == 32
-#define EEPROM_BYTE_ADDRESS_MASK 0x1f
-#elif EEPROM_PAGE_SIZE == 16
-#define EEPROM_BYTE_ADDRESS_MASK = 0x0f
-#elif EEPROM_PAGE_SIZE == 8
-#define EEPROM_BYTE_ADDRESS_MASK = 0x07
-#elif EEPROM_PAGE_SIZE == 4
-#define EEPROM_BYTE_ADDRESS_MASK = 0x03
-#else
-#error Unknown EEPROM page size!  Please add new byte address value!
-#endif
-#endif
-
-// Includes
-#include "protocol.h"
-#include "sp_driver.h"
-#include "eeprom_driver.h"
-#include "uart.h"
-#include "watchdog.h"
-
-// Functions
-uint8_t get_char(void);
-void send_char(uint8_t c);
-uint16_t get_word(void);
-
-uint8_t BlockLoad(unsigned size, uint8_t mem, uint32_t *address);
-void BlockRead(unsigned size, uint8_t mem, uint32_t *address);
-
-uint16_t crc16_block(uint32_t start, uint32_t length);
+
+
+// Protocol
+enum {
+  CMD_SYNC                = '\x1b',
+
+  // Informational
+  CMD_CHECK_AUTOINCREMENT = 'a',
+  CMD_CHECK_BLOCK_SUPPORT = 'b',
+  CMD_PROGRAMMER_TYPE     = 'p',
+  CMD_DEVICE_CODE         = 't',
+  CMD_PROGRAM_ID          = 'S',
+  CMD_VERSION             = 'V',
+  CMD_HW_VERSION          = 'v', // Unsupported extension
+  CMD_READ_SIGNATURE      = 's',
+
+  // Addressing
+  CMD_SET_ADDRESS         = 'A',
+  CMD_SET_EXT_ADDRESS     = 'H',
+
+  // Erase
+  CMD_CHIP_ERASE          = 'e',
+
+  // Block Access
+  CMD_BLOCK_LOAD          = 'B',
+  CMD_BLOCK_READ          = 'g',
+  CMD_BLOCK_CRC           = 'i',
+
+  // Byte Access
+  CMD_READ_BYTE           = 'R',
+  CMD_WRITE_LOW_BYTE      = 'c',
+  CMD_WRITE_HIGH_BYTE     = 'C',
+  CMD_WRITE_PAGE          = 'm',
+  CMD_WRITE_EEPROM_BYTE   = 'D',
+  CMD_READ_EEPROM_BYTE    = 'd',
+
+  // Lock and Fuse Bits
+  CMD_WRITE_LOCK_BITS     = 'l',
+  CMD_READ_LOCK_BITS      = 'r',
+  CMD_READ_LOW_FUSE_BITS  = 'F',
+  CMD_READ_HIGH_FUSE_BITS = 'N',
+  CMD_READ_EXT_FUSE_BITS  = 'Q',
+
+  // Control
+  CMD_ENTER_PROG_MODE     = 'P',
+  CMD_LEAVE_PROG_MODE     = 'L',
+  CMD_EXIT_BOOTLOADER     = 'E',
+  CMD_SET_LED             = 'x',
+  CMD_CLEAR_LED           = 'y',
+  CMD_SET_TYPE            = 'T',
+};
+
+
+// Memory types for block access
+enum {
+  MEM_EEPROM              = 'E',
+  MEM_FLASH               = 'F',
+  MEM_USERSIG             = 'U',
+  MEM_PRODSIG             = 'P',
+};
+
+
+// Command Responses
+enum {
+  REPLY_ACK               = '\r',
+  REPLY_YES               = 'Y',
+  REPLY_ERROR             = '?',
+};