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'm not that much into assemler, so I try to reuse existing asm-code as i2c-driver. I've found original Philips code for that. I try now to link it with c-code but get always linker warnings. Any help appreciated!
NAME . . . . . . . . . USAGE MODULE NAMES -------------------------------------------- ?C_START . . . . . . . CODE; ** L51 GENERATED ** ?C_STARTUP ?C_STARTUP . . . . . . CODE; ?C_STARTUP ASMS ?IIC_TEST_DEVICE . . . CODE; IIC_DRIVER ?IIC_TEST_DEVICE?BYTE. DATA; IIC_DRIVER ?INIT_IIC?BYTE . . . . DATA; IIC_DRIVER ?_IIC_WRITE_SUB?BYTE . ILLEGAL ** UNRESOLVED ** ASMS IIC_ERROR. . . . . . . BIT; IIC_DRIVER MAIN . . . . . . . . . CODE; ASMS _IIC_WRITE_SUB . . . . ILLEGAL ** UNRESOLVED ** ASMS _INIT_IIC. . . . . . . CODE; IIC_DRIVER ASMS *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL SYMBOL: _IIC_WRITE_SUB MODULE: asms.obj (ASMS) *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL SYMBOL: ?_IIC_WRITE_SUB?BYTE MODULE: asms.obj (ASMS) *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: ?_IIC_WRITE_SUB?BYTE MODULE: asms.obj (ASMS) ADDRESS: 0277H *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: _IIC_WRITE_SUB MODULE: asms.obj (ASMS) ADDRESS: 027FH
#include <REG552.H> #include "iic.h" #define myIICaddr 0x55 // my own i2c slave address /*------------------------------------------------ MAIN C Function ------------------------------------------------*/ void main (void) { unsigned char reg = 0; // Init routines Init_IIC(myIICaddr); // set control-register: stop counting, enable alarm reg = 0xC4; if(IIC_Write_Sub(RTC_ADDRESS, 1, , 0x00) != I2C_OK) { // error } while (1) { ; } }
$LIST $REGISTERBANK (0,1) $NOSYMBOLS $PAGEWIDTH (130) NAME IIC_DRIVER ; ; Includes: EQREG652.ASM ; $NOLIST $INCLUDE (EQREG652.ASM) $LIST ; ; Public labels defined in this Module: ; ************************************* public ?IIC_Test_Device public ?IIC_Test_Device?BYTE public _Init_IIC public ?Init_IIC?BYTE ; $EJECT ; ...snipp... ?BI?IICBit Segment Bit Rseg ?BI?IICBit ; public IIC_Error IIC_Error: dbit 1 ; IIC Error Bit ; ?BA?IICBitAdr Segment Data BitAddressable Rseg ?BA?IICBitAdr ; IICCntrl: ds 1 ; Bit Addressable IIC Control Register ; ?DT?IICPar Segment Data Rseg ?DT?IICPar ?IIC_Test_Device?BYTE: ?IIC_Write?BYTE: ?Init_IIC?BYTE: ; SlaveAddress: ds 1 ; Slave Address Include R/W DataCount1: ds 1 ; Block 1 Count DataIndex1: ds 1 ; Block 1 Transfer Buffer Address SubAddress: ds 1 ; Sub Address ( If Any ) DataCount2: ds 1 ; Block 2 Count DataIndex2: ds 1 ; Block 2 Transfer Buffer Address ; $EJECT ; $EJECT IICCode Segment Code InBlock Rseg IICCode ; ...snipp... ***************************************************************** ; * Init_IIC: * ; * PROCEDURE ( OwnSlaveAddress ) ; * ; * DECLARE OwnSlaveAddress BYTE ; * ; * * ; * Initialises the IIC SIO1 data, sets the Own Slave Address * ; * * ; * NOTE: This procedure must be called * ; * after power on before use of any other IIC procedure * ; ***************************************************************** _Init_IIC: mov s1adr,SlaveAddress ; Setup Own Slave Address mov s1con,#NSTA_NSTO_AA ; Assert Acknowledge on Slave Address mov IICCntrl,#0 ; Initialise Control / Status Register setb es1 ; Enable SIO1 Interrupt
The error messages are telling you that the _IIC_WRITE_SUB function and its argument space (?_IIC_WRITE_SUB?BYTE) was not found. I don't see them in the listing you posted. Jon
no, they are all there (the posting size limited it). But it must be something with the syntax I assume with this funny '?' & '_'
To export a symbol from an assembler module, you need to declare it "public". Near the top of the assembly file you posted, I see:
; Public labels defined in this Module: ; ************************************* public ?IIC_Test_Device public ?IIC_Test_Device?BYTE public _Init_IIC public ?Init_IIC?BYTE
The _ and ? are documented in the manual here: http://www.keil.com/support/man/docs/c51/c51_ap_progobj.htm Jon
no, I think the code is ok so far. I've took it from Philips Application Note: AN89004. The only thing I can imagine is that it declared to be: "PLM51 I2C software interface". But the code is written completely in asm! Rolf
The naming convention is the key to the problem, but not necessarily the problem itself, here. Different compilers use different conventions for argument passing and name mapping from source language to actual object file symbols. If that ASM file is meant to be used with PLM/51, you'll have to *tell* Keil C51 about that fact. PLM/51 is in the index of the Cx51 manual --- go look for yourself.
Even though all your fine input, I still believe it must be something with syntax or asm <-> c-code. When I look at the map file generatet I see the the functions public and later illegal:
B:0022H.1 SEGMENT IICBIT D:0020H SEGMENT IICBITADR D:0010H SEGMENT IICPAR C:10F6H SEGMENT IICCODE C:164DH SEGMENT IICINITCODE C:165BH SEGMENT IICINTCODE C:0E00H SEGMENT IICINTSTATES C:1117H PUBLIC ?IIC_READ D:0010H PUBLIC ?IIC_READ?BYTE C:1111H PUBLIC ?IIC_READ_STATUS D:0010H PUBLIC ?IIC_READ_STATUS?BYTE C:1101H PUBLIC ?IIC_READ_SUB D:0010H PUBLIC ?IIC_READ_SUB?BYTE C:10F6H PUBLIC ?IIC_TEST_DEVICE D:0010H PUBLIC ?IIC_TEST_DEVICE?BYTE C:110DH PUBLIC ?IIC_WRITE D:0010H PUBLIC ?IIC_WRITE?BYTE C:10FDH PUBLIC ?IIC_WRITE_MEMORY D:0010H PUBLIC ?IIC_WRITE_MEMORY?BYTE C:1105H PUBLIC ?IIC_WRITE_SUB D:0010H PUBLIC ?IIC_WRITE_SUB?BYTE C:1122H PUBLIC ?IIC_WRITE_SUB_READ D:0010H PUBLIC ?IIC_WRITE_SUB_READ?BYTE C:1109H PUBLIC ?IIC_WRITE_SUB_SWINC D:0010H PUBLIC ?IIC_WRITE_SUB_SWINC?BYTE C:111EH PUBLIC ?IIC_WRITE_SUB_WRITE D:0010H PUBLIC ?IIC_WRITE_SUB_WRITE?BYTE C:164DH PUBLIC ?INIT_IIC D:0010H PUBLIC ?INIT_IIC?BYTE B:0022H.1 PUBLIC IIC_ERROR ...snipp... INTER-MODULE CROSS-REFERENCE LISTING ------------------------------------ NAME . . . . . . . . . . . USAGE MODULE NAMES ------------------------------------------------ ...snipp... ?IIC_READ. . . . . . . . . CODE; IIC ?IIC_READ?BYTE . . . . . . DATA; IIC ?IIC_READ_STATUS . . . . . CODE; IIC ?IIC_READ_STATUS?BYTE. . . DATA; IIC ?IIC_READ_SUB. . . . . . . CODE; IIC ?IIC_READ_SUB?BYTE . . . . DATA; IIC PAGE RTC ?IIC_TEST_DEVICE . . . . . CODE; IIC ?IIC_TEST_DEVICE?BYTE. . . DATA; IIC ?IIC_WRITE . . . . . . . . CODE; IIC ?IIC_WRITE?BYTE. . . . . . DATA; IIC ?IIC_WRITE_MEMORY. . . . . CODE; IIC ?IIC_WRITE_MEMORY?BYTE . . DATA; IIC ?IIC_WRITE_SUB . . . . . . CODE; IIC ?IIC_WRITE_SUB?BYTE. . . . DATA; IIC RTC ?IIC_WRITE_SUB_READ. . . . CODE; IIC ?IIC_WRITE_SUB_READ?BYTE . DATA; IIC ?IIC_WRITE_SUB_SWINC . . . CODE; IIC ?IIC_WRITE_SUB_SWINC?BYTE. DATA; IIC ?IIC_WRITE_SUB_WRITE . . . CODE; IIC ?IIC_WRITE_SUB_WRITE?BYTE. DATA; IIC ?INIT_IIC. . . . . . . . . CODE; IIC ?INIT_IIC?BYTE . . . . . . DATA; IIC ASMS ...snipp... IIC_ERROR. . . . . . . . . BIT; IIC IIC_READ_SUB . . . . . . . ILLEGAL ** UNRESOLVED ** PAGE RTC IIC_WRITE_SUB. . . . . . . ILLEGAL ** UNRESOLVED ** RTC INITLCD. . . . . . . . . . CODE; LCD ASMS INIT_GLOBALS . . . . . . . CODE; RTC ASMS INIT_IIC . . . . . . . . . ILLEGAL ** UNRESOLVED ** ASMS
The error messages you listed before are telling you that the _IIC_WRITE_SUB function and its argument space (?_IIC_WRITE_SUB?BYTE) were not found. I don't see them in the listing you posted. I do see ?IIC_WRITE_SUB and ?IIC_WRITE_SUB?BYTE but these are not the same. Also, the unresolved symbols in this listing: IIC_READ_SUB, IIC_WRITE_SUB, and INIT_IIC are not included in the listing. ?IIC_READ_SUB, ?IIC_WRITE_SUB, and ?IIC_INIT are included, but these names do not match. Jon
"The only thing I can imagine is that it declared to be: 'PLM51 I2C software interface'. But the code is written completely in asm!" Have you actually read the code of this App Note, or have you just grabbed the code and ignored the text? I've just taken a brief glance at the 1st couple of pages of the PDF, and the following are immediately obvious - in the first two paragraphs: "...intended for Intel PLM51 users ... provide an Intel PLM51 user with a set of procedures..." It doesn't say that it's written in PLM; it says it's for use by PLM programs! It even says explicitly: "These procedures have been coded in Intel ASM51..." Note that C51 is not the same as PLM51! If you want to interface this code to C51, you will have to adapt it yourself. There is a chapter in the C51 Manual entitled "Interfacing C to Assembler" - you must read it! It will tell you how to interface your assembler code to C51. http://www.keil.com/support/man/docs/c51/c51_ap_ctoasm.htm
I seriously doubt our OP is capable of manipulating those ASM sources such that they compile and link correctly with C51. He may succeed declaring them alien though, since the routines in question are supposed to behave like PL/M51 routines, even though they're coded in assembly. So telling C51 that they're PL/M51 code should allow to link them.
The Philips 552 micro utilizes the same interface. Here is a clip from the header file for the function calls:
// +----------------------------------------------------------------------+ // | | // | I2C552M.h - I2C Master Processing Functions Definitions | // | | // +----------------------------------------------------------------------+ // // NOTE: All references to "SlaveAddress" below expect an eight bit address // with the low order bit 0. To get this use the macro SetSlaveAddr(Addr) // as the first argument of the call. The macro simply doubles the 7-bit // address. // // Before doing any I2C functions, a call MUST be made to I2C_Initialize. // // All functions return with C=0 if the message was handled without errors. // In addition, the bit variable I2C_Error contains the same status value. /*----------------------------------------------------------------------------*/ // // ***************************************************************** // * * // * Explanation of Symbols Used in Message Format Comments * // * * // * Slv - SlaveAddress * // * SlvW - SlaveAddress + Write * // * SlvR - Slave Address + Read * // * Sub - SubAddress * // * D1[0..L-1] - Array of Data Bytes ( DataIndex1 ) * // * L - Length of Array D1 ( DataCount1 ) * // * D2[0..M-1] - Array of Data Bytes ( DataIndex2 ) * // * M - Length of Array D2 ( DataCount2 ) * // * S - Start Condition * // * P - Stop Condition * // * A - Acknowledge * // * N - Negative Acknowlege * // * * // ***************************************************************** #define SetSlaveAddr(Addr) (Addr+Addr) typedef unsigned char uchar; typedef uchar idata * I2CBuf; /*-- Function Prototypes ---------------------------------------------------*/ extern alien void I2C_Initialize (uchar OwnSlaveAddress); /*----------------------------------------------------------------------------*/ extern alien bit I2C_Write ( uchar SlaveAddress, uchar Count, I2CBuf SourcePtr ); // IIC Format: // // S SlvW A D1[0] A D1[1] A ..... A D1[L-1] A P /*----------------------------------------------------------------------------*/ extern alien bit I2C_Write_Sub ( uchar SlaveAddress, uchar Count, I2CBuf SourcePtr, uchar SubAddr ); // IIC Format: // // S SlvW A Sub A D1[0] A D1[1] A ..... A D1[L-1] A P
now I'm completly lost. To what code belongs this header file? Well, see. I've a 80c552 module with different i2c components attached to it. I desperatly try to find a genric driver to read and write to this bus (bytes or block of bytes). I've looked at several places and the best I found was this PL/M thing. This functions covers exaxtly my need. If someone can point me to a driver that works with my c-code I'll more than happy!!
now I'm completly lost. To what code belongs this header file? Well, see. I've a 80c552 module with different i2c components attached to it. I desperatly try to find a genric driver to read and write to this bus (bytes or block of bytes). I've looked at several places and the best I found was this PL/M thing. This functions covers exactly my need. If someone can point me to a driver that works with my c-code I'll more than happy!!
" To what code belongs this header file?" Read the 1st line of Bob's post - he tells you what it is & where it comes from! Bob's code illustrates Hans-Bernhard's suggestion to use the C51 'alien' keyword. The 'alien' keyword allows C51 to call PL/M functions. The assembler code you are referring to is written to interface to PL/M - as it says in the Application Note.