none
Issue when I add a new variable RRS feed

  • Question

  • Ok, I am hesitant to post this, and I've repeated the experiment many times over, but I fear I'll look like an introductory programmer when you guys read this.

    I have a function in my Driver called OCT_Write().  For a long time, nothing was in it and so no harm was done when the calling application executed a WriteFile().  (Basically, the calling app was set up to do CreateFile(), WriteFile(), ReadFile() and I happened to get XXX_Read working and so now I am doing XXX_Write.)

    When OCT_Write was empty, my OCT_Read could correctly read 8 consecutive bytes from my RAM (something else, unrelated to CE, puts them there).  So knowing that I have the OCT_Read working, I went ahead and started adding code for OCT_Write.  First I put this in:

    WCHAR dbgBuf[100];
    
    wsprintf(dbgBuf, _T("OCT_Write() of %d bytes."), Count);
    OutputDebugStringW(dbgBuf);
    
    return Count;

    and everything was fine.  I could see "OCT_Write() of 3 bytes." printed in my debug output AND when the OCT_Read happened, the correct 8 bytes were still read back properly.

    Now, if I declare any new variable in OCT_Write, such as this:

    WCHAR dbgBuf[100];
    DWORD x;

    wsprintf(dbgBuf, _T("OCT_Write() of %d bytes."), Count);
    OutputDebugStringW(dbgBuf);

    return Count;

    or this:

     

    WCHAR dbgBuf[100];
    int i = 0;

    wsprintf(dbgBuf, _T("OCT_Write() of %d bytes."), Count);
    OutputDebugStringW(dbgBuf);

    return Count;
    all of a sudden my OCT_Read method returns junk!  How can declaring just one new variable, either "int i = 0;" or "DWORD x;" cause such a problem?  The message "OCT_Write() of 3 bytes." still is printed in my debug output.

    Wednesday, July 7, 2010 9:16 PM

All replies

  • That seems a mystery, but without showing us your read function we won't
    be able to tell you anything. I suspect your read function is actually
    containing bad code overwriting some code/memory somewhere or reading
    from a position that was ok when the compiler compiled your driver code
    without the extra auto variable.
     
    Another point to note: there's no need to use a big buffer, wsprintf and
    OutputDebugStringW. Just use RETAILMSG or DEBUGMSG, or better, use the
    debug logging templates I created (free download) here:
    http://guruce.com/blogpost/atemplatefordebugmessages
     
    Using a RETAILMSG your code could look like:
     
    RETAILMSG(1, (L"OCT_Write() of %d bytes.", Count));
     
    output: "OCT_Write() of 3 bytes."
     
     
    using the GuruCE debug logging templates from the link above:
     
    LOGMSG(ZONE_INFO, L"%d bytes.", Count);
     
    output: "ModuleName: OCT_Write> 3 bytes."
     
    And you can even decorate all your functions with:
     
    FUNC_ENTRY(L"pBuffer = 0x%08X", pBuffer);
     
    output: "ModuleName: +OCT_Write(pBuffer = 0x12345678)+"
     
    FUNC_EXIT(L"%s", retValue ? L"TRUE" : L"FALSE");
     
    output: "ModuleName: +OCT_Write(TRUE)+"
     
     
    As you can see, the GuruCE debug logging template automatically takes
    care of the function name and you can define the ModuleName to whatever
    you like.
     
    If only Microsoft would implement the GuruCE debug logging templates
    system wide we would have consistent and great debug logging for all
    components and drivers in Windows CE...
     

    Good luck,

    Michel Verhagen, eMVP
    Check out my blog: http://guruce.com/blog

    GuruCE
    Microsoft Embedded Partner
    http://guruce.com
    Consultancy, training and development services.
    Thursday, July 8, 2010 3:14 AM
    Moderator
  • What does "returns junk" mean to you?  To me it means that the value of Count is changed between the wsprintf call and the return.

    Does the code that you show actully show the problem that you are discussing, or is it made up for this discussion?


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com
    Thursday, July 8, 2010 12:56 PM
    Moderator
  • There is a compile time variable that can be used to insert the funtion name.  Not as capable as Michel's implementation, but better than typing in the function name...

    RETAILMSG(1, (L"%S: My message\r\n", __FUNCTION__))

    The __FUNCTION__ parameter has the name of the function in ascii, the %S (note - capital S) interprets the corresponding parameter as opposite whatever the string is (interprets the parameter as ascii if it is used in a UNICODE string and vice versa)


    Dean Ramsier eMVP BSQUARE Corporation
    Thursday, July 8, 2010 1:07 PM
  • Where is the RAM location that stores your 8 bytes, and where is the RAM location that contains your program memory?
    Dean Ramsier eMVP BSQUARE Corporation
    Thursday, July 8, 2010 1:11 PM
  • That seems a mystery, but without showing us your read function we won't
    be able to tell you anything. I suspect your read function is actually
    containing bad code overwriting some code/memory somewhere or reading
    from a position that was ok when the compiler compiled your driver code
    without the extra auto variable.

    Here is my XXX_Read function:

     

    DWORD OCT_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
    {
    	unsigned char * dpr = (unsigned char *)gMemBase;
    	WCHAR dbgBuf[100];
    	int i = 0;
    	USHORT usData;
    
    	// Implement the code to read from the stream device
    	// here. OCT_Init set up information on where ram is
    	// (gMemBase).
    	wsprintf(dbgBuf, _T("OCT_Read() of %d bytes."), Count);
    	OutputDebugStringW(dbgBuf);
    
    	//gMemBase will get incremented after each read, so the
    	// next time we will be starting at a different place. I'll
    	// probably want to implement a function to reset, or
    	//move around, gMemBase.
    	//for (i=0; i< Count; i++)
    		//((unsigned char *)pBuffer)[i] = READ_REGISTER_UCHAR(gMemBase++);
    	//The above attempt doesn't work smoothly in that after
    	// every 2 bytes read it "reads back" 2 bytes of 0x00.
    	//Instead of hacking around that, I can just read
    	//unsigned shorts instead.
    	for (i=0; i < Count; i+=2) {
    		usData = READ_REGISTER_USHORT((PUSHORT)gMemBase);	//get 2 bytes
    		((unsigned char *)pBuffer)[i] = usData & 0xff;
    		((unsigned char *)pBuffer)[i+1] = (usData >> 8) & 0xff;
    
    		//You would assume I would only want to increment
    		// by 2 here, but if I do that then I have the same 
    		//problem as when reading UCHARS - for every 2
    		//legitimate bytes I get 2 bytes of 0x00. I can 
    		//increment by 4 to get past the 2 bytes of 0x00.
    		gMemBase += 4;
    	}
    
    	return Count;
    }
    Note that my application calls WriteFile BEFORE ReadFile. Also, my ram is 16-bit, hence why I have those issues with getting 0x00 that I refer to in my comments.

     

    • Edited by mr_jeff Thursday, July 8, 2010 1:55 PM added 16 bit ram sentence
    Thursday, July 8, 2010 1:53 PM
  • What does "returns junk" mean to you?  To me it means that the value of Count is changed between the wsprintf call and the return.

    Oh, sorry, by return I meant the bytes that XXX_Read was putting into the pBuffer array.  The value of Count was correct at all times.  I can summarize like this:

    IF (XXX_Write is NOT called) THEN

            XXX_Read puts 8 correct bytes in pBuffer,

            My application sees 8 correct bytes

    ELSE IF (XXX_Write has no extra var declared) THEN

            XXX_Read puts 8 correct bytes in pBuffer,

            My application sees 8 correct bytes

    ELSE IF (XXX_Write has DWORD x; declared) THEN

            XXX_Read has 8 unrecognizable bytes,

            My application sees 8 unrecognizable bytes

    ELSE IF (XXX_Write has int i = 0; declared) THEN

            XXX_Read has 8 unrecognizable bytes,

            My application sees 8 unrecognizable bytes

    END IF

     

    (I put in code in XXX_Read to test the value coming from READ_REGISTER_USHORT, that's how I can tell.  Of course, with that code added to XXX_Read now XXX_Read always returns the wrong bytes.)

     

    Does the code that you show actully show the problem that you are discussing, or is it made up for this discussion?

    That is legitimate code that I used repeatedly in the test.  I didn't believe my eyes at first, so I made sure to perform the test with that code multiple times with and multiple times without the "DWORD x;" or "int i = 0;" declarations inserted.
    • Edited by mr_jeff Thursday, July 8, 2010 2:49 PM formatting
    Thursday, July 8, 2010 2:35 PM
  • You are incrementing your global pointer, so if you call this a second time, what data gets read?

    Again, what do you mean by "returns junk"?


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com
    Thursday, July 8, 2010 2:36 PM
    Moderator
  • You are incrementing your global pointer, so if you call this a second time, what data gets read?

    Again, what do you mean by "returns junk"?

    I could try breaking the XXX_Read into two 4-byte reads (see, there's only 8 bytes of known data in this RAM) but I thought this issue would be independent of multiple calls to XXX_Read, since XXX_Write doesn't have the code (it's commented out) to increment the pointer.

    I think we were posting at the same time.  I have trouble formatting my table like I wanted to in the post above, but I am referring to what comes back from READ_REGISTER_USHORT and put into pBuffer and given to my application.  That is what is junk.  Of course, if I modify XXX_Read to examine the data coming back from READ_REGISTER_USHORT then it always appears to be unrecognizable bytes, so I can't so for sure if READ_REGISTER_USHORT is the issue or if copying into pBuffer is the issue.

    Thursday, July 8, 2010 2:43 PM
  • Where is the RAM location that stores your 8 bytes, and where is the RAM location that contains your program memory?
    Dean Ramsier eMVP BSQUARE Corporation

    The RAM that stores the 8 bytes is on a PCI card in the CEPC machine.  I assume my program memory is stored in RAM on the CEPC's motherboard.  So they should be independent.
    Thursday, July 8, 2010 2:51 PM
  • I think I can close this thread down.  After getting rid of the wsprintf and OutputDebugStringW calls and re-doing how I do my writes, it looks like things are working.  I wish I knew why I was seeing the strange behavior I was, but it's probably not worth tracking down.  And the code I have now is modified enough that if I kept posting to this tread, the initial problem would morph out of control.

    Thanks for the responses though.  I still learned alot by reading everyone's responses, and when I get a chance I will use those new debugging methods for printing instead.
    Thursday, July 8, 2010 9:55 PM