copy interrupt vector from ROM to RAM -- IAR ARM

All design tool related questions: compiler, assembler, linker. Embedded programming questions: assembler, C code.

Moderator: nferre

thavali
Posts: 6
Joined: Thu Oct 23, 2008 8:13 am

copy interrupt vector from ROM to RAM -- IAR ARM

Sat Mar 07, 2009 6:21 am

hi all,

I am using IAR ARM complier for AT91SAM7S256. In demo code of IAR, in file board_cstartup_iar.s which is used to start-up MCU before go to main function, I do not find the piece code operate copy interrupt vector from ROM to RAM. I want to know how can interrupt vector be copied from ROM to RAM. following is code of board_cstartup_iar.s.


*****************************************************
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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.
* ----------------------------------------------------------------------------
*/

/*
IAR startup file for AT91SAM7S microcontrollers.
*/

MODULE ?cstartup

;; Forward declaration of sections.
SECTION IRQ_STACK:DATA:NOROOT(2)
SECTION CSTACK:DATA:NOROOT(3)

//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------

#define __ASSEMBLY__
#include "board.h"

//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------

#define ARM_MODE_ABT 0x17
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_SVC 0x13
#define ARM_MODE_SYS 0x1F

#define I_BIT 0x80
#define F_BIT 0x40

//------------------------------------------------------------------------------
// Startup routine
//------------------------------------------------------------------------------
SECTION .ro_vectors :CODE:NOROOT(2)

//PUBLIC resetVector
//PUBLIC rom_reset
PUBLIC __iar_program_start
ARM

//rom_reset:
__iar_program_start:
LDR pc, =label ; Reset
/*
Exception vectors
*/
SECTION .vectors :CODE:NOROOT(2)

PUBLIC resetVector
PUBLIC irqHandler

EXTERN Undefined_Handler
EXTERN SWI_Handler
EXTERN Prefetch_Handler
EXTERN Abort_Handler
EXTERN FIQ_Handler

ARM

__iar_init$$done: ; The interrupt vector is not needed
; until after copy initialization is done

resetVector:
; All default exception handlers (except reset) are
; defined as weak symbol definitions.
; If a handler is defined by the application it will take precedence.
LDR pc, =resetHandler ; Reset
LDR pc, Undefined_Addr ; Undefined instructions
LDR pc, SWI_Addr ; Software interrupt (SWI/SVC)
LDR pc, Prefetch_Addr ; Prefetch abort
LDR pc, Abort_Addr ; Data abort
B . ; RESERVED
LDR pc, =irqHandler ; IRQ
LDR pc, FIQ_Addr ; FIQ

Undefined_Addr: DCD Undefined_Handler
SWI_Addr: DCD SWI_Handler
Prefetch_Addr: DCD Prefetch_Handler
Abort_Addr: DCD Abort_Handler
FIQ_Addr: DCD FIQ_Handler

/*
Handles incoming interrupt requests by branching to the corresponding
handler, as defined in the AIC. Supports interrupt nesting.
*/
irqHandler:
/* Save interrupt context on the stack to allow nesting */
SUB lr, lr, #4
STMFD sp!, {lr}
MRS lr, SPSR
STMFD sp!, {r0, lr}

/* Write in the IVR to support Protect Mode */
LDR lr, =AT91C_BASE_AIC
LDR r0, [r14, #AIC_IVR]
STR lr, [r14, #AIC_IVR]

/* Branch to interrupt handler in Supervisor mode */
MSR CPSR_c, #ARM_MODE_SVC
STMFD sp!, {r1-r3, r12, lr}
MOV lr, pc
BX r0
LDMIA sp!, {r1-r3, r12, lr}
MSR CPSR_c, #ARM_MODE_IRQ | I_BIT

/* Acknowledge interrupt */
LDR lr, =AT91C_BASE_AIC
STR lr, [r14, #AIC_EOICR]

/* Restore interrupt context and branch back to calling code */
LDMIA sp!, {r0, lr}
MSR SPSR_cxsf, lr
LDMIA sp!, {pc}^


/*
After a reset, execution starts here, the mode is ARM, supervisor
with interrupts disabled.
Initializes the chip and branches to the main() function.
*/
SECTION .cstartup:CODE:NOROOT(2)

PUBLIC resetHandler
EXTERN LowLevelInit
EXTERN main
REQUIRE resetVector
ARM

resetHandler:

/* Set pc to actual code location (i.e. not in remap zone) */
LDR pc, =label

/* Perform low-level initialization of the chip using LowLevelInit() */
label:
LDR r0, =LowLevelInit
LDR r4, =SFE(CSTACK)
MOV sp, r4
MOV lr, pc
BX r0

/* Set up the interrupt stack pointer. */
MSR cpsr_c, #ARM_MODE_IRQ | I_BIT | F_BIT ; Change the mode
LDR sp, =SFE(IRQ_STACK)

/* Set up the SVC stack pointer. */
MSR cpsr_c, #ARM_MODE_SVC | F_BIT ; Change the mode
LDR sp, =SFE(CSTACK)

/* Branch to main() */
LDR r0, =main
MOV lr, pc
BX r0

/* Loop indefinitely when program is finished */
loop4:
B loop4

END

****************************************************************

following is file LowLevelInit

***************************************
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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.
* ----------------------------------------------------------------------------
*/

//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------

#include "board.h"
#include "board_memories.h"

//------------------------------------------------------------------------------
// Internal definitions
//------------------------------------------------------------------------------

/// \internal Startup time of main oscillator (in number of slow clock ticks).
#define BOARD_OSCOUNT (AT91C_CKGR_OSCOUNT & (0x40 << Cool)

/// \internal USB PLL divisor value to obtain a 48MHz clock.
#define BOARD_USBDIV AT91C_CKGR_USBDIV_1

/// \internal PLL frequency range.
#define BOARD_CKGR_PLL AT91C_CKGR_OUT_0

/// \internal PLL startup time (in number of slow clock ticks).
#define BOARD_PLLCOUNT (16 << Cool

/// \internal PLL MUL value.
#define BOARD_MUL (AT91C_CKGR_MUL & (72 << 16))

/// \internal PLL DIV value.
#define BOARD_DIV (AT91C_CKGR_DIV & 14)

/// \internal Master clock prescaler value.
#define BOARD_PRESCALER AT91C_PMC_PRES_CLK_2

//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Default spurious interrupt handler. Infinite loop.
//------------------------------------------------------------------------------
void defaultSpuriousHandler(void)
{
while (1);
}

//------------------------------------------------------------------------------
/// Default handler for fast interrupt requests. Infinite loop.
//------------------------------------------------------------------------------
void defaultFiqHandler(void)
{
while (1);
}

//------------------------------------------------------------------------------
/// Default handler for standard interrupt requests. Infinite loop.
//------------------------------------------------------------------------------
void defaultIrqHandler(void)
{
while (1);
}

//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Performs the low-level initialization of the chip. This includes EFC, master
/// clock, AIC & watchdog configuration, as well as memory remapping.
//------------------------------------------------------------------------------
void LowLevelInit(void)
{
unsigned char i;

// Set flash wait states in the EFC
// 48MHz = 1 wait state
#if defined(at91sam7s512)
AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS;
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS;
#elif defined(at91sam7s32) || defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) || defined(at91sam7s256)
AT91C_BASE_MC->MC_FMR = AT91C_MC_FWS_1FWS;
#else
#error No chip definition ?
#endif

// Initialize main oscillator
AT91C_BASE_PMC->PMC_MOR = BOARD_OSCOUNT | AT91C_CKGR_MOSCEN;
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS));

// Initialize PLL at 96MHz (96.109) and USB clock to 48MHz
AT91C_BASE_PMC->PMC_PLLR = BOARD_USBDIV | BOARD_CKGR_PLL | BOARD_PLLCOUNT
| BOARD_MUL | BOARD_DIV;
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK));

// Wait for the master clock if it was already initialized
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));

// Switch to slow clock + prescaler
AT91C_BASE_PMC->PMC_MCKR = BOARD_PRESCALER;
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));

// Switch to fast clock + prescaler
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK;
while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY));

// Initialize AIC
AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF;
AT91C_BASE_AIC->AIC_SVR[0] = (unsigned int) defaultFiqHandler;
for (i = 1; i < 31; i++) {

AT91C_BASE_AIC->AIC_SVR = (unsigned int) defaultIrqHandler;
}
AT91C_BASE_AIC->AIC_SPU = (unsigned int) defaultSpuriousHandler;

// Unstack nested interrupts
for (i = 0; i < 8 ; i++) {

AT91C_BASE_AIC->AIC_EOICR = 0;
}

// Enable Debug mode
AT91C_BASE_AIC->AIC_DCR = AT91C_AIC_DCR_PROT;

// Watchdog initialization
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;

// Remap the internal SRAM at 0x0
BOARD_RemapRam();

// Disable RTT and PIT interrupts (potential problem when program A
// configures RTT, then program B wants to use PIT only, interrupts
// from the RTT will still occur since they both use AT91C_ID_SYS)
AT91C_BASE_RTTC->RTTC_RTMR &= ~(AT91C_RTTC_ALMIEN | AT91C_RTTC_RTTINCIEN);
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;

}
----------------------------------

thanks,
gerhardf
Posts: 552
Joined: Thu Dec 02, 2004 2:28 pm

Re: copy interrupt vector from ROM to RAM -- IAR ARM

Sat Mar 07, 2009 11:47 am

thavali wrote:hi all,
I am using IAR ARM complier for AT91SAM7S256. In demo code of IAR, in file board_cstartup_iar.s which is used to start-up MCU before go to main function, I do not find the piece code operate copy interrupt vector from ROM to RAM. I want to know how can interrupt vector be copied from ROM to RAM. following is code of board_cstartup_iar.s.
i would assume that you are speaking about the debug configuraton where the code is copied to ram and not to flash. the interrupt vector table isn't copy from rom to ram. the debugger of the iar workbench is remapping ram to address 0x0000 0000 and then loading the whole code to this address.

regards
gerhard
thavali
Posts: 6
Joined: Thu Oct 23, 2008 8:13 am

Re: copy interrupt vector from ROM to RAM -- IAR ARM

Sun Mar 08, 2009 7:36 am

Thank gerhardf,

as comment from you, the remapping RAM to 0x00 will be operated before loading interrupt vector to 0x0200 0000 ?. And compiler will compile and place the code of interrupt vector in address 0x00 of Image file ? I am using simulator of IAR to debug code in flash. I see after remap RAM to address 0x00 , then program go to __iar_copy_init2 routine to copy interrupt vector to RAM, after that, program go to main function.
anyone can description more about this problem.

Thanks,

Return to “Development Tools”

Who is online

Users browsing this forum: No registered users and 2 guests