IAR - Stack Organization in IAR complier

when I use CodeVisionAVR for 8 bit AVR, then RAM Memory Organization consist (attached file):

  • Registers.

  • The Data Stack: area is used to dynamically store local variables, passing function parameters and saving registers R0, R1, R15, R22, R23, R24, R25, R26, R27, R30, R31 and SREG during interrupt routine servicing.

The Data Stack Pointer is implemented using the Y register.

  • The Global Variables area is used to statically store the global variables during program execution. The size of this area can be computed by summing the size of all the declared global variables.

  • The Hardware Stack area is used for storing the functions return addresses.

The SP register is used as a stack pointer and is initialized at start-up with value of the HEAP_START -1 address.

During the program execution the Hardware Stack grows downwards to the Global Variables area.

  • The Heap is a memory area located between the Hardware Stack and the RAM end.

It is used by the memory allocation functions from the Standard Library: malloc, calloc, realloc and free.

but, in IAR for ARM, then I can not find memory area in SRAM correlative with The Hardware Stack area of CodevisionAVR. Where is used to store the functions return addresses ?

for example: with a recursive function, size of LR register is not enough to store return addresses.

The stack in in ARM doesn’t exist in any particular location, and it is a combined data and return address stack (as defined by the ARM ABI specification). You can easily create your own stacks anywhere in memory, where there is room to grow downwards. In fact, this is what any operating system does.

ARM (at least in the v5 processor core) accomplishes function calls in two ways: BL (Branch and Link) and literally writing the PC with a new value( “long jump”). BL stores the return address in a register called LR. Your compiler should then generate code which pushes LR onto the stack, and is popped off at the end of the function. The “long jump” method requires moving the PC to LR and then moving the call address into PC as a two step operation.

Your compiler should then generate code which pushes LR onto the stack, and is popped off at the end of the function.

Thanks theatrus,

That, I can find in stack where in the stack is used to store local variables, where in the stack is used to store return addresses, or those works which complier should operate in auto and we can not control, handle ?.

Thanks

Check some of the outputted assembly code. It should either make a reference from the stack pointer for local variables, or use another register as a frame pointer and do roughly the same thing.

If you’re doing straight up C/C++ you don’t need to concern yourself with this. Only if you’re coding more than a few lines of assembly will it matter.

Thanks,

you can explain organization memory in IAR or keil complier ?.

for example, section for code, section for data (in data section, it consist: global data, stack data, heap data…).

and the way complier create and place these section in the image program.

thavali

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 << 8))

/// \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 << 8)

/// \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;

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