This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problems in saving (and parameter passing ) a 32 bit value in the flash.

I took this sentence from the Getting started manual:
".. or if too many arguments are
involved, fixed memory locations are used for those extra arguments."

How do I use this?
I intend to to do the follwing
iap_programming_flash_data_dword(long int value, unsigned int address );
and
iap_programming_flash_data_word(long int value, unsigned int address );

  • The C51 Users' Guide has a good discussion of the compiler's calling conventions in the "Interfacing C to Assembler" section.

    Up to three parameters can be passed in registers. Any extra parameters will be assigned memory locations by the compiler in which to pass the parameters.

    Sometimes less than three parameters can be passed, depending on argument size and the order of the arguments. Your function illustrates one of the more unfortunate cases. 32-bit arguments are passed in R4-R7. A 16-bit argument #2 would be passed in R4-R5. But those registers are already used by argument #1. So, arg 2 will be passed in memory.

    (Why "unfortunate"? Because there's still the slot for 16-bit arg #3, R2-R3, available. But the code generator isn't quite flexible enough to make use of those registers for argument #2; it's a little hung up on the argument order and number, as well as just size.)

    One way to finesse this problem, in this case, is if that second argument really is an address (a pointer). In that case, you can take advantage of the fact that a generic pointer, unlike a 16-bit memory specific pointer, will always be passed in R1-R3. Declare the function as

    void f(U8* address, U32 value);

    and you can have both arguments passed in registers. (Of course, that call will use 7 of your 8 registers, and you may find it difficult to do anything with them without spilling the arguments into some temporary storage yourself.)

  • I implemented my self a assbembly code and I call it from a C function.So as I am already using R2 and R3 for the address (r2 and R3 hold the low and high part of DPTR). I think its not neccessary to do what you are suggesting.Am I wrong?

    Here is the assembly code I worte to implemnt:
    ; **********************************************************************
    ; function: iap_program_data_dword SEGUNDA VERSAO
    ; prototype: unsigned char iap_program_data_byte(unsigned char val, unsigned int addr);
    ; description: programs a byte in the flash. passed is the byte and the
    ; 16-bit address. zero is returned for success, non zero is returned for
    ; failiure.
    ; **********************************************************************
    RSEG ?PR?_iap_program_data_dword?IAP
    _iap_program_data_dword:
    PUSH IE ; disable interrupts
    CLR EA
    MOV A,CMOD
    MOV R2,A ; store copy of CMOD
    JNB ACC.6,?IAPTWDOG ; if watchdog enabled then disable
    ANL CMOD,#0BFH
    ?IAPTWDOG:
    ORL AUXR1,#020H ; enable bootrom
    MOV R0,iap_freq ; osc frequency
    MOV R1,#02H

    MOV DPH,R2 ; address to program
    MOV DPL,R3

    MOV A ,R4 ; data to write
    CALL 0FFF0H ; call iap routine
    MOV R7,A ; id in accumulator

    INC DPTR
    MOV A,R5 ; data to write
    CALL 0FFF0H ; call iap routine
    MOV R7,A ; id in accumulator

    INC DPTR
    MOV A,R6 ; data to write
    CALL 0FFF0H ; call iap routine
    MOV R7,A ; id in accumulator

    INC DPTR
    MOV A ,R7 ; data to write
    CALL 0FFF0H ; call iap routine
    MOV R7,A ; id in accumulator

    ANL AUXR1,#0DFH ; disable bootrom
    MOV CMOD,R2 ; restore CMOD (restore watchdog state)
    POP IE ; restore interrupts to initial state
    RET
    ; end of iap_program_data_dword
    END

    Problem:
    1.The assembler and compiler sends a warning:
    REFERENCE MADE TO UNRESOLVED EXTERNAL
    I dont know why (maybe I am not paying the necessary attention!) but it seems that the compiler does not recognize the existence of such code.