extend "spminterface.h" by implementing "do_spm"
authorStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Sun, 19 Aug 2012 23:55:38 +0000 (01:55 +0200)
committerStephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
Mon, 20 Aug 2012 21:54:35 +0000 (21:54 +0000)
Signed-off-by: Stephan Baerwolf <stephan.baerwolf@tu-ilmenau.de>
firmware/spminterface.h

index d67c3e9..2fca2cd 100644 (file)
@@ -90,6 +90,70 @@ ret
 #ifndef BOOTLOADER_ADDRESS
 // this header is the interface for user-code
 
+#ifndef funcaddr___bootloader__do_spm
+  #if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__)
+    #define  funcaddr___bootloader__do_spm 0x1826
+    
+  #else
+    #error "unknown MCU - where is bootloader__do_spm located?"
+  #endif
+#endif
+
+
+/*
+ * Call the "bootloader__do_spm"-function, located within the BLS via comfortable C-interface
+ * During operation code will block - disable or reset watchdog before call.
+ * 
+ * 
+ * REMEMBER: interrupts have to be disabled! (otherwise code may crash non-deterministic)
+ * 
+ */
+void do_spm(const uint32_t flash_byteaddress, const uint8_t spmcrval, const uint8_t r1_highdatabyte, const uint8_t r0_lowdatabyte) {
+    uint8_t loaddr = (flash_byteaddress >>  0) & 0xff;
+    uint8_t hiaddr = (flash_byteaddress >>  8) & 0xff;
+    uint8_t adaddr = (flash_byteaddress >> 16) & 0xff;
+  
+    asm volatile (
+    "push r0\n\t"  
+    "push r1\n\t"  
+      
+    "mov r13, %[hiaddr]\n\t"
+    "mov r12, %[loaddr]\n\t"
+    "mov r11, %[adaddr]\n\t"
+      
+      
+    /* high8 of address of bootloader__do_spm */
+    "ldi r18, %[hi8spmfunc]\n\t"
+    "mov r31, r18\n\t"
+    
+    /* low8 of address of bootloader__do_spm */
+    "ldi r18, %[lo8spmfunc]\n\t"
+    "mov r30, r18\n\t"
+    
+    /* also load the spmcrval */
+    "mov r18, %[spmcrval]\n\t"
+
+    /* correkt address of bootloader__do_spm from bytes into words */
+    "lsr r31\n\t"
+    "ror r30\n\t"
+    
+    "mov r1, %[hidata]\n\t"
+    "mov r0, %[lodata]\n\t"
+
+    /* finally call the bootloader-function */
+    "icall\n\r"
+
+    "pop  r1\n\t"  
+    "pop  r0\n\t"  
+
+    :
+    : [loaddr] "r" (loaddr), [hiaddr] "r" (hiaddr), [adaddr] "r" (adaddr), [spmcrval] "r" (spmcrval),
+      [lodata] "r" (r0_lowdatabyte), [hidata] "r" (r1_highdatabyte),
+      [hi8spmfunc] "M" (funcaddr___bootloader__do_spm >> 8), [lo8spmfunc] "M" (funcaddr___bootloader__do_spm & 0xff)
+
+    : "r0","r1","r11","r12","r13","r18"
+    );
+}