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

call by value does not work

Hello,

I'm trying to pass a variable to a function, but the value stored in the variable never arrives. When I pass a constant, however, the value is handed over. An example follows:

main.c
extern void TransmitHex( unsigned char hexval );

main{
unsigned char var;
var = 0x41;
TransmitHex( 0x41 ); // produces an "A" in ASCII
TransmitHex( var ); // nothing shows up, possibly 0x00 is transmitted
}
---
serial.c

void TransmitHex ( unsigned char hexval){
/* transmit hexval via serial port */
}

I've tried to locate var with NEAR and FAR, but the problem persists. I'm using the HLARGE memory model. I have an external RAM connected to the ST10, address window is configured properly.

any ideas?

regards,
Soenke

  • Looks like the user stack is not located to a RAM space. Check the linker map file and verify that you have for the user stack a valid RAM area.

    • I've searched my linker file and found the following code lines

      CLASSES    ( OSE_C  (0002000h-0004FFFh),
      		      NCODE  (0005000h-0007FFFh),
                   NCONST (0005000h-0007FFFh),
                   ICODE  (0006000h-00061FFh),
                   FCONST (0018000h-008FFFFh),
                   HCONST (0018000h-008FFFFh),
                   XCONST (0018000h-00DFFFFh),
                   FCODE  (0018000h-008EFFFh),
                   SROM   (008F000h-008FFFFh),
      
                   NDATA   (0108000h-010BFFFh),
                   NDATA0  (0108000h-010BFFFh),
                   FDATA   (0105000h-010FFFFh),
                   FDATA0  (0105000h-010FFFFh),
                   HDATA   (010C000h-011FFFFh),
                   HDATA0  (010C000h-011FFFFh),
                   XDATA   (010C000h-017CFFFh),
                   XDATA0  (010C000h-017CFFFh),
                   OSE_X   (0108000h-010BFFFh),
                   OSE_P   (0104000h-0104FFFh),
                   OSE_I   (000F600h-000FDFFh),
                   IDATA   (000F600h-000FDFFh),
                   IDATA0  (000F600h-000FDFFh) )
      
      
      SECTIONS   ( ?C_INITSEC (05000h),
                   ?C_CLRMEMSEC,
                   ?C_STARTUP_CODE%ICODE(07000h),
                   OS166_ZDATA%OSE_I(0FC00h),
                   ?PR?PFLASH%FLASH_CODE(100000h)[!],
                   ?C_USERSTACK%NDATA(0108000h) )
      

      So the User Stack would point at the starting address of the NEAR Date area. Might that be the cause of the problem?

      0x108000 is in the external memory area, according to my datasheet. I've an external memory attached, the memory window is configured to start address 0x100000, range is 512k, so that shouldn't cause trouble.

      • Looks like no error in the linker setup. Can you run a debugger in your target hardware to see that the RAM really works?

        • I would ask what you are doing in the function "TransmitHex"? What does your listing show for the code sequence? Looking at your code the call would be identical since you initialize the variable in the function than call it. From the list file you would get something like below.

          E6F84100      MOV       R8,#041H
          DA000000 E    CALLS     SEG (TransmitHex),TransmitHex
          E6F84100      MOV       R8,#041H
          DA000000 E    CALLS     SEG (TransmitHex),TransmitHex
          

          • TransmitHex takes the higher and lower quadlet of the passed byte, converts them into ASCII and puts them out on the serial, so I can view them via terminal on my PC. The function works as long as I pass a hex value directly like this:

            TransmitHex(0x41) // puts out A in ASCII

            I had inserted a short delay in this function, and the counter inside seemed to be a part of the problem. I've tried the following code to narrow the problem down:

            main
            {
               unsigned char a = 0x41;     // A in ASCII
               unsigned char b = 0x42;     // B in ASCII
               TransmitHex(a);             // puts out B!
               TransmitHex(b);             // again B
               TransmitHex(0x41);          // puts out C
            
               unsinged char c = 0x43;     // C in ASCII
               TransmitHex(c);             // puts out C
            }
            

            the counter inside TransmitHex has been removed, there are no more temporary variables inside the function left.

            • Time to look into your TransmitHex function. Maybe the bug is there.

              • here is the code for TransmitHexByte()

                typedef unsigned char byte;
                
                void TransmitHexByte(byte sendstr)
                {
                  S0TIR = OFF;          // clear transmit
                  S0TBUF = 0x30;	// send "0" ASCII
                  while(S0TIR == OFF){}	// wait
                  S0TIR = OFF;
                  S0TBUF = 0x78;        // send "x" ASCII
                  while(S0TIR == OFF){}
                
                  S0TIR = OFF;
                  S0TBUF = ConvertQuadToChar(sendstr >> 4); // send character for higher quadlet
                
                  while(S0TIR == OFF){}
                
                  S0TIR = OFF;
                  S0TBUF = ConvertQuadToChar(sendstr); // send character for lower quadlet
                  while(S0TIR == OFF){}
                  S0TIR = OFF;
                  S0TBUF = 0x20;  // send space
                  while(S0TIR == OFF){}
                }
                
                
                byte ConvertQuadToChar(byte zeichen)
                {
                  // mask higher quadlet
                  zeichen &= (byte) 0x0F;
                  // if lower quadlet is between 0 and 9, add Offset +0x30
                  if ((zeichen >= 0x00) && (zeichen < 0x0A))
                  {
                    zeichen += 0x30;
                  }
                  // if lower quadlet is between A and F, add Offset +0x37
                  else if (zeichen > 0x09 && zeichen < 0x10)
                  {
                    zeichen += 0x37;
                  }
                  return zeichen;
                }
                

                • I don't use ST but I tried your example on a C167 and don't have a problem.

                  Sorry, but looks like you have a problem with some settings somewhere. Here is a complete example using your code (without start167.a66) that works correctly on hyperterminal.

                  Data: "0x41 0x42 0x41 0x43"

                  #include <reg167.h>
                  
                  typedef	unsigned char	   byte;  /*  8 bit */
                  #define OFF 0
                  
                  byte ConvertQuadToChar(byte zeichen) {
                    // mask higher quadlet
                    zeichen &= (byte) 0x0F;
                    // if lower quadlet is between 0 and 9, add Offset +0x30
                    if ((zeichen >= 0x00) && (zeichen < 0x0A)) {
                      zeichen += 0x30;
                    }
                    // if lower quadlet is between A and F, add Offset +0x37
                    else if (zeichen > 0x09 && zeichen < 0x10) {
                      zeichen += 0x37;
                    }
                    return zeichen;
                  }
                  
                  void TransmitHexByte(byte sendstr) {
                    S0TIR = OFF;          // clear transmit
                    S0TBUF = 0x30;	// send "0" ASCII
                    while(S0TIR == OFF){}	// wait
                    S0TIR = OFF;
                    S0TBUF = 0x78;        // send "x" ASCII
                    while(S0TIR == OFF){}
                  
                    S0TIR = OFF;
                    S0TBUF = ConvertQuadToChar(sendstr >> 4); // send character for higher quadlet
                  
                    while(S0TIR == OFF){}
                  
                    S0TIR = OFF;
                    S0TBUF = ConvertQuadToChar(sendstr); // send character for lower quadlet
                    while(S0TIR == OFF){}
                    S0TIR = OFF;
                    S0TBUF = 0x20;  // send space
                    while(S0TIR == OFF){}
                  }
                  
                  void SendData(void) {
                     unsigned char a = 0x41;     // A in ASCII
                     unsigned char b = 0x42;     // B in ASCII
                     unsigned char c = 0x43;     // C in ASCII
                  
                     TransmitHexByte(a);         // puts out B!
                     TransmitHexByte(b);         // again B
                     TransmitHexByte(0x41);      // puts out C
                     TransmitHexByte(c);         // puts out C
                  }
                  
                  void main(void) {
                    P3  |= 0x0400;
                    DP3 |= 0x0400;
                    DP3 &= 0xF7FF;
                    S0TIC = 0x80;
                    S0RIC = 0x00;
                    S0BG  = 0x40;
                    S0CON = 0x8011;
                  
                    SendData();
                    while(1);
                  }
                  
                  

                  • Can you run your code in a debugger on the target hardware?

                    • Think I've found the cause. I've relocated the NEAR memory area to on chip memory, and suddenly the code works. Might be a timing problem with the external RAM.

                      Thanks for the helpful input!

                      Regards,
                      Soenke

                      0