We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I need to save a 32 bit variable to the flash. I am using the In Application Programming.I wrote a code starting from the function "program data byte" (in my case I made program_data_dword). The problem is that I receive the Warning: "REFERENCE MADE TO UNRESOLVED EXTERNAL", which means that the cpompiler does not find the code. I use the registers R4 to R7 to receive the long int value and R3 and R2 to save the address. Can anyone explain what I doing wrongly? Thanks. Amilcar Here is the code: ; ********************************************************************** ; function: iap_program_data_byte ; prototype: unsigned char iap_program_data_byte(unsigned char val, unsigned int addr); ; description: programs a dword 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
Looks to me like your code lacks the PUBLIC declarator. Compare your asm source to that generated from a dummy C implementation using the #pragma SRC to fix this kind of problem. And next time you report an error message, please make sure quote the complete text of it. In this case, you omitted which function the linker complained about being undefined.
Here is the error message: Build target 'Target 1' assembling IAP.a51... compiling IAP2.c... linking... *** ERROR L127: UNRESOLVED EXTERNAL SYMBOL SYMBOL: ?_iap_program_data_dword?BYTE MODULE: MAIN4.obj (MAIN4) *** ERROR L128: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: ?_iap_program_data_dword?BYTE MODULE: MAIN4.obj (MAIN4) ADDRESS: 100068DH Program Size: data=24.1 xdata=571 const=0 code=3354 Target not created
void main(void) { com_config_timer1(); com_config_serialIO(); com_baudrate (4800); sys_ini(); while(1) { while (status != MEM_FREE) { printf("Memoria ocupada!, Vou passar p o proximo endereco\n"); addr = addr + INCREM; }//if status = iap_read_data_byte(addr); }// while (status != MEM_LIVRE) iap_program_data_dword(longitude, addr); //armazena if (status == 1) printf("Programming sucess!...\n"); }
It sounds like you have specified NOREGPARMS or you have set the OPTIMIZE level so low that register parameters are not used. Jon
"...I receive the Warning: "REFERENCE MADE TO UNRESOLVED EXTERNAL", which means that the cpompiler does not find the code. I use the registers R4 to R7 to receive the long int value and R3 and R2 to save the address. Can anyone explain what I doing wrongly?..." It was not the compiler but linker and it didn't look for code but for a variable that had been declared (by compiler) as an external one. You cannot simply choose which registers you will use for function parameters. In case of your function iap_program_data_dword the compiler expects the first parameter is passed in R4 to R7 registers and the second parameter in fixed memory locations. Parameters passed to assembly routines in fixed memory locations use segments named ?function_name?BYTE, (in your case ?_iap_program_data_dword?BYTE). See the "Interfacing C Programs to Assembler" section, Chapter 6. Advanced Programming Techniques in C51.pdf (HLP dir), esp. "Parameter Passing in Fixed Memory Locations" "...All parameters are assigned space in these segments even if they are passed using registers. Parameters are stored in the order in which they are declared in each respective segment." It explains the offset +04H and +05H of the unsigned int addr parameter in the segment ?_iap_program_data_dword?BYTE. My advice: When interfacing C programs to assembler, the best way (in my opinion) to do it is to write a short "test" C program like this:
// declare the proposed function: extern void iap_program_data_dword(unsigned long longitude, unsigned int addr); void main(void) { // call it: iap_program_data_dword(0x12345678, 0x9ABC); }
MOV R7,#078H ; LSB of unsigned long longitude MOV R6,#056H ; ... MOV R5,#034H ; ... MOV R4,#012H ; MSB of unsigned long longitude MOV ?_iap_program_data_dword?BYTE+04H,#09AH ; MSB of unsigned int addr MOV ?_iap_program_data_dword?BYTE+05H,#0BCH ; LSB of unsigned int addr LCALL _iap_program_data_dword