Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Embedded C and Microcontrollers Memory

Status
Not open for further replies.

sukumar

Junior Member level 3
Joined
Nov 18, 2006
Messages
31
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,286
Activity points
1,464
Hi All,

I have come across a doubt, Assume I have written a code eg. a simple LED blinking code for PIC Micro-controller. In that program I used three variables called 'x' and declared it as int x=AA,y=0xaa and delay_cnst(Local). Now I built the project. The build will give hex file. I burned the hex file into microcontroller. Now the microcontroller has only the hex file and all the variable i used will be in hex file only(Program memory) ie No data memory involved. Finally my question is how the data's (Global and Local Variables)are arranged in program memory and how they copied to data memory? How they are initialized? where the value 220 stored in my program etc.

Suggest me some books or tutorial to read more about these things.

Code:
#include <pic.h>

__CONFIG(0x3f72);

unsigned char x=0xAA, y=0x55;
void DelayMs(unsigned int Ms);

void main()
{
	DelayMs(10);
	TRISD  =  0x00;				//PORTD Configured as O/P
	while(1)
	{
		PORTD = x;
		DelayMs(500);
		PORTD = y;
		DelayMs(500);
	}
}

void DelayMs(unsigned int Ms)
{
	int delay_cnst;
	while(Ms>0)
	{
		Ms--;
		for(delay_cnst = 0;delay_cnst <220;delay_cnst++);
	}
}
 
Last edited:

The values for the variables are stored in program memory.
When the program is compiled, the linker links in, or generates a start up file.
When the program runs, the start up file runs first to initialise globals and configure anything else required.
It then calls your main function.

Here is a start up file used by the Microchip C30 compiler. crt0.s

Code:
;; 
;; C Run-time startup module for dsPIC30 C compiler.
;; (c) Copyright 2002,2004,2007 Microchip Technology, All rights reserved
;;
;; Primary version, with data initialization support.
;; The linker loads this version when the --data-init
;; option is selected.
;; 
;; See file crt1.s for the alternate version without
;; data initialization support.
;; 
;; Entry __reset takes control at device reset and
;; performs the following:
;;
;;  1. initialize stack and stack limit register
;;  2. initialize PSV window if __const_length > 0
;;  3. process the data initialization template
;;  4. call the user's _main entry point
;;
;; Assigned to section .init, which may be allocated
;; at a specific address in linker scripts. 
;;
;; Supports the zero-parameter form of main() by default.
;; If the symbol __ARGV is defined, supports the two-parameter
;; form of main().
;;
;; Un-comment the following line to define symbol __ARGV:
;;      .equiv __ARGV,1
;; 
        
        .equ __30F2010, 1   
        .include "p30f2010.inc"

        .section .init,code

        .global __resetPRI
        .ifdef __C30ELF
        .type   __resetPRI,@function
        .endif
__resetPRI:     
        .weak   __reset
        .ifdef __C30ELF
        .type   __reset,@function
        .endif
__reset:
;;
;; Initialize stack, PSV, and data
;; 
;; registers used:  w0
;;
;; Inputs (defined by user or linker):
;;  __SP_init
;;  __SPLIM_init
;; 
;; Outputs:
;;  (does not return - resets the processor)
;; 
;; Calls:
;;  __psv_init
;;  __data_init
;;  _main or __main
;; 

        mov      #__SP_init,w15    ; initialize w15
        mov      #__SPLIM_init,w0  ; 
        mov      w0,_SPLIM         ; initialize SPLIM
        nop                        ; wait 1 cycle

        rcall    __psv_init        ; initialize PSV
        rcall    __data_init       ; initialize data
                                   ;  clears w0, so ARGC = 0

        .ifdef __ARGV
          rcall  __main            ; call two-parameter main() setup
        .else
          call  _main              ; call user's main()
        .endif

        .pword 0xDA4000            ; halt the simulator
        reset                      ; reset the processor


        .weak __psv_init
__psv_init:
;; 
;; Initialize PSV window if _constlen > 0
;; 
;; Registers used:  w0
;; 
;; Inputs (defined by linker):
;;  __const_length
;;  __const_psvpage
;; 
;; Outputs:
;;  (none)
;; 

        bclr     _CORCON,#PSV        ; disable PSV (default)
        mov      #__const_length,w0  ; 
        cp0      w0                  ; test length of constants
        bra      z,1f                ; br if zero

        mov      #__const_psvpage,w0 ; 
        mov      w0,_PSVPAG          ; PSVPAG = psvpage(constants)
        bset     _CORCON,#PSV        ; enable PSV

1:      return                       ;  and exit

        
        .weak __data_init
__data_init:
;; 
;; Process data init template
;;
;; The template is null-terminated, with records
;; in the following format:
;;
;; struct data_record {
;;  char *dst;        /* destination address  */
;;  int  len;         /* length in bytes      */
;;  int  format;      /* format code          */
;;  char dat[0];      /* variable length data */
;; };
;; 
;; Registers used:  w0 w1 w2 w3 w4 w5
;; 
;; Inputs (defined by linker):
;;  __dinit_tbloffset
;;  __dinit_tblpage
;; 
;; Outputs:
;;  (none)
;;
;; Calls:
;;  __memcpypd3
;; 
        .equiv   FMT_CLEAR,0    ;  format codes
        .equiv   FMT_COPY2,1    ; 
        .equiv   FMT_COPY3,2    ; 

        mov      #__dinit_tbloffset,w0 ; w0,w1 = template
        mov      #__dinit_tblpage,w1   ;
        bra      4f                    ; br to continue

1:      add      w0,#2,w0       ; template+=2
        addc     w1,#0,w1       ; 
        mov      w1,_TBLPAG     ; TBLPAG = tblpage(template)

        tblrdl.w [w0],w3        ; w3 = len 
        add      w0,#2,w0       ; template+=2
        addc     w1,#0,w1       ; 
        mov      w1,_TBLPAG     ; TBLPAG = tblpage(template)

        tblrdl.w [w0],w5        ; w5 = format
        add      w0,#2,w0       ; template+=2
        addc     w1,#0,w1       ; 
        clr      w4             ; upper = FALSE (default)

        cp       w5,#FMT_CLEAR  ; test format
        bra      nz,2f          ; br if not FMT_CLEAR

        ;; FMT_CLEAR - clear destination memory
        dec      w3,w3          ; decrement & test len
        bra      n,4f           ; br if negative

        repeat   w3             ; 
        clr.b    [w2++]         ; clear memory      
        bra      4f             ; br to continue

        ;; FMT_COPY2, FMT_COPY3 - copy bytes
2:      cp       w5,#FMT_COPY2  ; test format
        bra      z,3f           ; br if FMT_COPY2

        setm     w4             ; upper = TRUE

3:      rcall    __memcpypd3    ; copy 2 or 3 bytes

4:      mov      w1,_TBLPAG     ; TBLPAG = tblpage(template)
        tblrdl.w [w0],w2        ; w2 = next dst      
        cp0      w2             ; 
        bra      nz,1b          ; loop on non-zero dst

        retlw    #0,w0          ; exit (clears ARGC also)

        
__memcpypd3:
;; 
;; Copy data from program memory to data memory
;; 
;; Registers used:  w0 w1 w2 w3 w4 w5
;; 
;; Inputs:
;;  w0,w1 = source address   (24 bits)
;;  w2 = destination address (16 bits)
;;  w3 = number of bytes (even or odd)
;;  w4 = upper byte flag   (0 = false)
;; 
;; Outputs:
;;  w0,w1 = next source address (24 bits)
;; 

1:      mov      w1,_TBLPAG     ; TBLPAG = tblpage(src)
        mov      w0,w5          ; w5 =   tbloffset(src)
        add      w0,#2,w0       ; src+=2
        addc     w1,#0,w1       ;

        tblrdl.b [w5++],[w2++]  ; dst++ = lo byte
        dec      w3,w3          ; num--
        bra      z,2f           ; br if done

        tblrdl.b [w5--],[w2++]  ; dst++ = hi byte
        dec      w3,w3          ; num--
        bra      z,2f           ; br if done

        cp0      w4             ; test upper flag
        bra      z,1b           ; br if false

        tblrdh.b [w5],[w2++]    ; dst++ = upper byte
        dec      w3,w3          ; num--
        bra      nz,1b          ; br if not done

2:      return                  ; exit


        .ifdef __ARGV        
__main:
;; 
;; Initialize a stack frame to support
;;   the two-parameter form of main()
;; 
;; Registers used:  w0 w1
;;
;; Inputs:
;;  (none)
;;
;; Outputs:
;;  (none)
;;
;; Calls:
;;  _main
;; 
        lnk      #6             ; construct frame

        mov      #0,w0          ; store a null terminator
        mov.b    w0,[w15-6]     ;  for program name

        sub      w15,#6,w1
        mov      w1,[w15-4]     ; argv[0] = &pgmname             
        mov      w0,[w15-2]     ; argv[1] = 0

        mov      #1,w0          ; w0 = argc
        sub      w15,#4,w1      ; w1 = &argv
        call    _main           ; call the user's main()

        ulnk                    ; destroy frame
        return                  ;  and exit
        .endif

        .end
 

Hi,

Thanks for your immediate reply. I heard abt startup file once. I need still more clear explanation. I have seen the dis-assembly it shows only the program.

The values for the variables are stored in program memory.
How they are arranged in memory.

When the program is compiled, the linker links in, or generates a start up file
Is it depends on compiler? ie it links or generates startup or both?

When the program runs, the start up file runs first to initialise globals and configure anything else required.
How it differentiate the local and global variable?

It then calls your main function
Is it the reset vector?
 

Look more closely at the dis-assembly, if using Hi-tect you should find something like this:

; Auto-generated runtime startup code for final link stage.

Hi-Tech auto generates the start up code,
Mplab C30 has start up files to link in.

How constants are arranged in memory is compiler specific.

It only intialises globals, locals dont need it.

No, it is not the reset vector, it calls your main function.

Look at the start up file I have posted.

.ifdef __ARGV
rcall __main ; call two-parameter main() setup
.else
call _main ; call user's main()
.endif
 
Global and static variable are given a memory location by the compiler, this location is then initialised by the start up file which is dynamically generated at compilation time, this start up file copies the values from program memory into data memory so that they can be modified during run time. The reason that this is only done for global and static memory locations is because they will always exist, that is to say that even if they go out of scope they will retain there value and memory location when they come back within scope, this is different to local variables that only exist in memory for the duration of the function that they are created in, that is when you return from the function that the variables are created in all data stored in that memory location becomes undefined.
The place that global and static variables are stored is called the heap and is just an area of memory the same as where local variables are stored.
Global and local variables are identical in data memory, the only difference between them is the way in which the memory is allocated for them and how the compiler treats them during compilation - scope is just an abstract idea that is implemented by the compiler, the actual data itself is identical regardless of scope.

/Pheetuz
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top