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) )
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 }
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