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 have a serial EEPROM used as a far memory expansion. Writing and reading routines for an i2c bus are in a C-code:
void start_write (void far * w_addr) { wait_smb_free (); smb_address = (unsigned int)w_addr; // EEPROM address } void write_page (unsigned char w_count) { data_number = w_count; // number of data bytes. wait_smb_free (); } // write into an EEPROM void from_mem_into_eeprom (unsigned char far * wr_addr, unsigned int wr_count, unsigned char * wr_dataptr) { unsigned char wr_ii; while (wr_count) { smb_buffer[wr_ii] = *wr_dataptr; start_write (wr_addr); // cnt bytes if (wr_count < 8) wr_ii = wr_count; write_page (wr_ii); // cnt byte(s) wr_count -= wr_ii; } } void byte_into_eeprom (unsigned char far * bw_addr, unsigned char out_b) { start_write (bw_addr); smb_buffer[0] = out_b; // Data byte write_page (1); // 1 byte } void word_into_eeprom (unsigned int far * ww_addr, unsigned int out_w) { from_mem_into_eeprom ((void *)ww_addr, sizeof(int), (void *)&out_w); } void read_eeprom (void far * rd_addr, unsigned char rd_count) { wait_smb_free (SMB_Wait_Error); smb_address = (unsigned int)rd_addr; // EEPROM address data_number = rd_count; // number of data bytes. wait_smb_free (); // Wait for transfer to finish } unsigned char byte_from_eeprom (unsigned char far * br_addr) { read_eeprom (br_addr, sizeof(char)); return (smb_buffer[0]); } unsigned int word_from_eeprom (unsigned int far * wr_addr) { read_eeprom (wr_addr, sizeof(int)); return (*(unsigned int *)smb_buffer); }
XBANKING.A51 is something like this:
NAME ?C?XBANKING ; 'far' Memory Access Support PUBLIC ?B?SMEM, ?B?TMEM, ?B?UMEM, ?B?VMEM ;PUBLIC ?C?XPAGE1SFR, ?C?XPAGE1RST PUBLIC ?C?CLDXPTR, ?C?CSTXPTR, ?C?ILDXPTR, ?C?ISTXPTR PUBLIC ?C?PLDXPTR, ?C?PSTXPTR, ?C?LLDXPTR, ?C?LSTXPTR EXTRN CODE (_byte_from_eeprom, _byte_into_eeprom) EXTRN CODE (_word_from_eeprom, _word_into_eeprom) ?C?LIB_CODE SEGMENT CODE RSEG ?C?LIB_CODE ;---------------------------------------------------------------------- ; CLDXPTR: Load BYTE in A via Address given in R1/R2/R3 ?C?CLDXPTR: LCALL _byte_from_eeprom MOV A, R7 RET ;---------------------------------------------------------------------- ; CSTXPTR: Store BYTE in A via Address given in R1/R2/R3 ?C?CSTXPTR: MOV R5, A LCALL _byte_into_eeprom RET ;---------------------------------------------------------------------- ; ILDXPTR: Load WORD in A(LSB)/B(HSB) via Address given in R1/R2/R3 ?C?ILDXPTR: LCALL _word_from_eeprom RET ;---------------------------------------------------------------------- ; ISTXPTR: Store WORD in A(HSB)/B(LSB) via Address given in R1/R2/R3 ?C?ISTXPTR: MOV R5, B MOV R4, A LCALL _word_into_eeprom RET END
If I used direct calls to the routines, linking would done without failures:
byte_into_eeprom ((void *)&test_block_e.test_byte, 0x30); if (byte_from_eeprom ((void *)&test_block_e.test_byte) != 0x30) jj++; word_into_eeprom ((void *)&test_block_e.test_word, 0x60A1); if (word_from_eeprom ((void *)&test_block_e.test_word) != 0x60A1) jj++;
However, I’d like to assign a value to a variable:
void self_test_1 (void) { unsigned int result1, temp1; temp1 = meas_uct_cC(); result1 = 0; result1 |= check_value (test_block_e.battV = meas_bat_mV(),11000,13750); result1 |= check_value (test_block_e.vd3V = meas_3vd_mV(), 3150, 3450) << 2; result1 |= check_value (test_block_e.vd5V = meas_5vd_mV(), 4750, 5250) << 4; if (temp1 > 6000) hw_error |= OverHeat; test_block_e.hw_result |= result1; }
Test_block_e is a sample structure in the far memory. In this case local variables (result1 and temp1) are overwritten by local variable (out_w) in EEPROM writing routine. Linker makes only one byte difference:
00000001H SYMBOL DATA --- ww_addr 00000019H SYMBOL DATA WORD out_w 00000018H SYMBOL DATA WORD result1 0000001AH SYMBOL DATA WORD temp1
Are there any requirements if an external routine is called in XBANKING.A51?
Unfortunately, dedicated C code is difficult task for the linker also.
*** WARNING L57: UNCALLED FUNCTION, IGNORED FOR OVERLAY PROCESS NAME: _BYTE_INTO_EEPROM/SMB *** WARNING L57: UNCALLED FUNCTION, IGNORED FOR OVERLAY PROCESS NAME: _WORD_INTO_EEPROM/SMB *** WARNING L57: UNCALLED FUNCTION, IGNORED FOR OVERLAY PROCESS NAME: _BYTE_FROM_EEPROM/SMB *** WARNING L57: UNCALLED FUNCTION, IGNORED FOR OVERLAY PROCESS NAME: _WORD_FROM_EEPROM/SMB
As a workaround I'll skip XBANKING.A51 and direct accessing/assigning so far.