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.