A few questions - Regarding main() function

Status
Not open for further replies.

bharaths_jois

Newbie level 6
Joined
Dec 28, 2006
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Bangalore,Karnataka,India
Activity points
1,374
microchip __const_psvpage

Hi ppl, I have the following few questions

1. What is the prototype of main()? Is it compiler dependent?

2. Would seem like a vague question, but what will happen if I do have an exit out of the main() function in an embedded system, considering the main is called by ind_crt0 after initialization of the memory blocks, etc...?

3. Lets consider that the execution goes out of main (for the time being)... Is there anybody who would be willing to listen to what we return from main()?
 

__data_init microchip reset

Traditionaly, main() returns an int to the calling program, 0 for success and any other value, an error code. C began life in a unix enviroment.
Most embedded systems ignore the return value from main(), executing a reset when main() returns.
The source code for the start up file, 'ind_crt0' for your compiler is normaly provided. You could modify the source code to make some use of the return value from main().
 

Thank you for the reply. Further more, what about the arguments passed to main()? I, till now have not used any. It would be good if you could give me an example where in an Embedded System, arguments are passed to main and are used by main in the application, if any.
 

I can not think of an application in embedded code where passing arguments to main() would be of any use. Except maybe to make some code portable between processor variants.
Allthough there must be some situations where this is useful?
Here is the start up code from the Pic30 tools compiler. As you can see, if you define the symbol __ARGV, the two parameter version of main is supported.

main(int argc, char *argv[])


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
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…