From: Stephan Baerwolf Date: Wed, 1 Aug 2012 15:28:10 +0000 (+0200) Subject: make "bootloader__do_spm()" ready to go into production... X-Git-Tag: 2010-07-27-stephan-201208011730^0 X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/commitdiff_plain/1eeada2c30052b0a811ccb2fffedb4c31cc22d77 make "bootloader__do_spm()" ready to go into production... Signed-off-by: Stephan Baerwolf --- diff --git a/firmware/bootloaderconfig.h b/firmware/bootloaderconfig.h index 32b6654..e2710c0 100644 --- a/firmware/bootloaderconfig.h +++ b/firmware/bootloaderconfig.h @@ -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 diff --git a/firmware/main.c b/firmware/main.c index 2d54b47..d651ec3 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -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 #include #include @@ -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 index 0000000..5e9825e --- /dev/null +++ b/firmware/spminterface.h @@ -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 +#include + +#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