make "bootloader__do_spm()" ready to go into production... 2010-07-27-stephan-201208011730
authorStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Wed, 1 Aug 2012 15:28:10 +0000 (17:28 +0200)
committerStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Wed, 1 Aug 2012 15:33:00 +0000 (15:33 +0000)
Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
firmware/bootloaderconfig.h
firmware/main.c
firmware/spminterface.h [new file with mode: 0644]

index 32b6654..e2710c0 100644 (file)
@@ -93,34 +93,15 @@ these macros are defined, the boot loader usees them.
  * to erase itself from the bootregion
  */
 
-#define HAVE_DOSPM_TUNNELCMD       1
+#define HAVE_SPMINTEREFACE         1
 /*
- * When enabled, "HAVE_DOSPM_TUNNELCMD" will implement an PROGMEM ARRAY 
- * with up to 15 opcodes within BLS.
- * This array will be called "bootloader__do_spm", and implements the 
- * "do_spm" subroutine from atmels "Instruction Set Manual" Rev.0856I, page 140.
- * 
-do_spm:
-;input:        spmcrval determines SPM action
-;disable interrupts if enabled, store status
-;temp1 will be register:       r7
-;temp2 will be register:       r8
-;spmcrval will be register:    r9
-
-in     temp2, SREG     ; --> has to be done before calling
-cli                    ; --> has to be done before calling
-                       ;check for previous SPM complete
-wait:
-in     temp1, SPMCR
-sbrc   temp1, SPMEN
-rjmp   wait
-                       ;SPM timed sequence
-out    SPMCR, spmcrval
-spm
-                       ;restore SREG (to enable interrupts if originally enabled)
-out    SREG, temp2
-ret
- * 
+ * Since code within normal section of application memory (rww-section) is
+ * not able to call spm for programming flash-pages, this option (when
+ * enabled) will insert a small subroutine into the bootloader-section
+ * to enable applications to circumvent this limitation and make them
+ * able to program the flash in a similar way as the bootloader does, too.
+ * For further details see "spminterface.h", which implements this 
+ * feature.
  */
 
 #define HAVE_EEPROM_PAGED_ACCESS    1
index 2d54b47..d651ec3 100644 (file)
@@ -8,6 +8,8 @@
  * This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $
  */
 
+#include "spminterface.h"  /* must be included as first! */
+
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
@@ -95,37 +97,6 @@ typedef union longConverter{
 }longConverter_t;
 
 
-#if HAVE_DOSPM_TUNNELCMD
-/*
-do_spm:
-;input:        spmcrval determines SPM action
-;disable interrupts if enabled, store status
-;temp1 will be register:       r7
-;temp2 will be register:       r8
-;spmcrval will be register:    r9
-
-in     temp2, SREG     ; --> has to be done before calling
-cli                    ; --> has to be done before calling
-                       ;check for previous SPM complete
-wait:
-in     temp1, SPMCR
-sbrc   temp1, SPMEN
-rjmp   wait
-                       ;SPM timed sequence
-out    SPMCR, spmcrval
-spm
-                       ;restore SREG (to enable interrupts if originally enabled)
-out    SREG, temp2
-ret
-*/ 
-#if defined (__AVR_ATmega8__)
-  const uint16_t bootloader__do_spm[15] PROGMEM = {0xb68f , 0x94f8, 0xb677, 0xfc70, 0xcffd, 0xbe97, 0x95e8, 0xbe8f, 0x9508, 0x00, 0xFFFF, 0x95e8, 0x9508, 0x0000,  0xFFFF};
-#else
-  #error "bootloader__do_spm has to be adapted, since there is no guaranty for SREG==0x3f, SPMCR==0x37, SPMEN==0x00"
-#endif
-#endif
-
-
 #if BOOTLOADER_CAN_EXIT
 static uchar                   requestBootLoaderExit;
 #endif
diff --git a/firmware/spminterface.h b/firmware/spminterface.h
new file mode 100644 (file)
index 0000000..5e9825e
--- /dev/null
@@ -0,0 +1,107 @@
+/* Name: spminterface.h
+ * Project: USBaspLoader
+ * Author: Stephan Baerwolf
+ * Creation Date: 2012-08-01
+ * Copyright: (c) 2012 by Stephan Baerwolf
+ * License: GNU GPL v2 (see License.txt)
+ */
+
+#ifndef SPMINTERFACE_H_f70ba6adf7624275947e859bdbff0599
+#define SPMINTERFACE_H_f70ba6adf7624275947e859bdbff0599
+
+/*
+ * spminterface.h offers a lightweight interface by inserting
+ * an small machine-subroutine into the bootsection. (right 
+ * after the interrupt-vector-table)
+ * This subroutine can be called by normal code in order to 
+ * enable it to program the flash (and depending on BLB11-lockbit
+ * also the bootsection itself). Since SPM-calls from RWW-sections
+ * will fail to work. The Routine will be called "bootloader__do_spm".
+ * Its principle assembler-code is depicted below (real code is a
+ * little machinedependen).
+ * Interfaces will be the 8-bit registers r10..r13, for details 
+ * also see below. As also the pageaddress-registes (Z and rampZ)
+ * are interfaced via different registers, it is possible to call
+ * this routine via indirect call (icall).
+ * Traditionally it is also possible to rcall, therefore you can
+ * define "bootloader__do_spm" for your normal code via defsym at 
+ * linking time.
+ * Example for an atmega8: "-Wl,--defsym=transfer_point=0x1826"
+ * (since BOOTLOADER_ADDRESS is 0x1800 and there are 
+ * 2x19 = 38 = 0x26 byte for interrupts)
+ * 
+
+bootloader__do_spm:
+;disable interrupts (if enabled) before calling!
+;you may also want to disable wdt, since this routine may busy-loop
+;==================================================================
+;-->INPUT:
+;spmcr (spmcrval determines SPM action) will be register:      r10
+;MCU dependend RA(MPZ should be transfered within register:    r11
+;lo8(Z) should be transfered within register:                  r12
+;hi8(Z) should be transfered within register:                  r13
+
+;<-->USED/CHANGED:
+;temp0 will be register:                                       r11
+;temp1 will be register:                                       r12
+;temp2 will be register:                                       r13
+;Z (r31:r30) wil be changed during operation
+
+;<--OUT:
+;==================================================================
+
+;load pageaddress (Z) from r13:12 since it may was used for icall
+mov    rampZ,  r11
+mov    r30,    r12
+mov    r30,    r13
+
+wait:                  ;check for previous SPM complete
+in     temp1, SPMCR
+sbrc   temp1, SPMEN
+rjmp   wait
+
+out    SPMCR, spmcrval ;SPM timed sequence
+spm
+
+ret
+
+*
+*/ 
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+
+#ifndef BOOTLOADER_ADDRESS
+// this header is the interface for user-code
+
+
+
+
+#else /*ifndef BOOTLOADER_ADDRESS*/
+// this header is used directly within bootloader_do_spm
+#include "bootloaderconfig.h"
+
+#if HAVE_SPMINTEREFACE
+
+
+/*
+ * insert architecture dependend "bootloader_do_spm"-code
+ * 
+ * try to make this array as big as possible
+ * (so bootloader always uses 2kbytes flash)
+ */
+#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__)
+//assume  SPMCR==0x37, SPMEN==0x00
+const uint16_t bootloader__do_spm[30] PROGMEM = {0x0000, 0x2dec, 0x2ded, 0xb6c7, 0xfcc0, 0xcffd, 0xbea7, 0x95e8, 0x9508,
+                                                0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+                                                0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+                                                0xFFFF, 0xFFFF, 0xFFFF};
+#else
+  #error "bootloader__do_spm has to be adapted, since there is no architecture code, yet"
+#endif  
+
+
+#endif
+#endif /*ifdef BOOTLOADER_ADDRESS*/
+
+#endif