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

P89LPC932 and serial communication, strange phenomenon

Following set:
Two identical PCBs (my hardware design using the LPC932), one with the "real" MCU, other with connector adaptor to EPM900 board.
My software runs smooth on the emulator. I always send 24 bytes via COM5 (virtual COM port of FTDI232 USB-to-RS232 chip). The MCU processes the 24 bytes, executes a command, some routines and sends 24 bytes back to PC.
The 24 bytes are a certain telegram with a two byte header and a checksum at the end.
So far, so good. As I said, it runs smooth on the emu.
But when I flash the compiled hex file into the LPC932 on the other board and connect this board with USB (COM5), I can send the 24 bytes to COM5, but I receive an error code generated by my firmware telling me the header is wrong.
I found out that the last, the 24th byte, is somehow coming to the first position of the serial input buffer. Example:
PC sends: AA 55 00 FF .... FF 60
hardware should have: AA 55 00 FF ... FF 60
in the 24 byte input buffer, but it has: 60 AA 55 00 FF ... FF
No idea. Code is fine, I worked it out a thousand time. The whole buffer seems to be shifted. I repeat, this runs correct on the emu, which holds the same MCU.

The worst fact is, that sometimes the code in the "real" MCU runs correctly after being connected to supply voltage (USB), sometimes it doesn't. So the code must be ok.

Any clue?

Thanks for any help.

Parents
  • [I'll answer in English, for the benefit of the other readers here who don't know any German]


    Ja, aber welche Variablen?

    Those variables used by both the IRQ handler and the main routine, to communicated with each other. These must be declared volatile, or what you've observed is only the beginning of the strange behaviour you'll experience.

    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird

    How certain are you that this actually is initialized to zeros? Did you check that, in a debugger session?

    Meine Vermutung geht dahin, daß der Keil-Compiler da was nicht richtig macht.

    I don't think you have shown anywhere near conclusive data to draw any such conclusion.

    4k-Code-Begrenzung des Compilers

    That limitation only exists in the, well, "limited" editions of the compiler. If you're really going to work with this stuff, do yourself a favour and get a full version.

Reply
  • [I'll answer in English, for the benefit of the other readers here who don't know any German]


    Ja, aber welche Variablen?

    Those variables used by both the IRQ handler and the main routine, to communicated with each other. These must be declared volatile, or what you've observed is only the beginning of the strange behaviour you'll experience.

    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird

    How certain are you that this actually is initialized to zeros? Did you check that, in a debugger session?

    Meine Vermutung geht dahin, daß der Keil-Compiler da was nicht richtig macht.

    I don't think you have shown anywhere near conclusive data to draw any such conclusion.

    4k-Code-Begrenzung des Compilers

    That limitation only exists in the, well, "limited" editions of the compiler. If you're really going to work with this stuff, do yourself a favour and get a full version.

Children
  • Ok, let's continue in English.

    Those variables used by both the IRQ handler and the main routine, to communicated with each other. These must be declared volatile, or what you've observed is only the beginning of the strange behaviour you'll experience.

    Oh! This is finally something I can use. My variables are currently global. Whether static nor volatile. In case STATIC isn't used, I assume the compiler will generate a static variable like an Assembler would do. A fixed memory address for every variable. If it isn't so, where should I know how the compiler is working? I'll try this out...

  • I notice that you are taking a rather naive approach to handling your messages. What happens if there is a glitch on the communication line? I would recommend that you do some synchronization to assure that messages are valid and properly framed.

    This might include validating the header bytes as you receive the message, checking for time-outs on partial messages, etc.

  • Oh! This is finally something I can use. My variables are currently global. Whether static nor volatile. In case STATIC isn't used, I assume the compiler will generate a static variable like an Assembler would do. A fixed memory address for every variable. If it isn't so, where should I know how the compiler is working? I'll try this out...
    static oe not makes no difference for global variables. What you have to take care of is ints that are used in both an ISR and main(). If you read these in main() with interrupts enabled, you will get sporadic failures.

    One more thing: re. "it works on the dev. board, not on my board"
    is EVERYTHING identical, I doubt it, list even subtle differences.

    Erik

  • Oh! This is finally something I can use. My variables are currently global. Whether static nor volatile. In case STATIC isn't used, I assume the compiler will generate a static variable like an Assembler would do. A fixed memory address for every variable. If it isn't so, where should I know how the compiler is working? I'll try this out...
    static oe not makes no difference for global variables. What you have to take care of is ints that are used in both an ISR and main(). If you read these in main() with interrupts enabled, you will get sporadic failures.

    One more thing: re. "it works on the dev. board, not on my board"
    is EVERYTHING identical, I doubt it, list even subtle differences.

    Erik

  • Suggest a review of startup.a51 and/or init.a51 for clearing or initializing XDATA.
    Bradford

  • Suggest a review of startup.a51 and/or init.a51 for clearing or initializing XDATA.
    The file is called STARTUP932.A51 here and contains a XDATALOOP which clears XDATA memory. Anyway, XDATA isn't used by me anymore, because it's not usable somehow (even if I active the "use XRAM (0x00 - 0x1ff)" option for the target. The result is totally weird. As if the compiled code wasn't able to access any XDATA area.

  • Meanwhile I tried this:

    - changed the declaration of all variables related to ISR and serial reception to VOLATILE XDATA and after this didn't work to VOLATILE IDATA -> no change to the error

    - changed the usage of register banks in ISR (before I had no "using 2" or similiar in the code) -> no change to the error

    - set the NOAREGS directive for all .c files (there is a recommendation to do so in the Keil C51 manual concerning ISRs and function calls) -> no change to the error

    The buffer is now assigned to IDATA (before was DATA, but this has no remarkable effect, it's just to let the compiler use the full range of IDATA), like all other variables. The code works fine in the emulator and in the simulator. But still not in the MCU....

    Perhaps I should try all those things described above together?

  • As if the compiled code wasn't able to access any XDATA area.

    You probably didn't set up your startup.a51 to activate xdata, then. No, setting "use XRAM ..." in the device options page does not do that for you.

    Given the amount of things you apparently don't know, I suggest you take a break from your current project and re-learn the basics. Check out the tutorials and manuals and really work through them, slowly.

  • I've fixed it by creating a workaround.
    The first byte coming in is checked to be 0xAA while the byte counter is still zero.
    If not, the counter won't be incremented.

    But the phenomenon still remains...

    There is, somehow, an additional byte coming into the SBUF which, after an interrupt occurred, is read and written into my I/O buffer.

    Anyway, thanks for your help, pals!

  • your code

    ESR = 1; // enable serial interrupt
    REN = 1; // enable serial reception
    while (1)


    I have, for a reason I have forgot (it was definitely needed in one case), the practice of doing the following. Try it
    RI = 0;
    TI = 0;
    ESR = 1; // enable serial interrupt
    REN = 1; // enable serial reception
    while (1)

    Erik

  • I also tried to set both flags to zero. The RI flag has been done before, because I reckoned an additional byte coming in somehow into the SBUF. After your suggestion I also tried TI, both didn't help. Just the workaround brought some success:

    void rx_int (void) interrupt 4 using 1
    {
    	uchar *ptr_c;
            uchar rxtemp;
    
    	if (RI)
    	{
    	   RI = 0;
    	   KB3 = 1;
    	   rxtemp = SBUF;
    	   ptr_c = &io_header; // copy byte by byte to receive buffer
               ptr_c += rxcount;
               *ptr_c = SBUF;
    	   if (rxcount == 0 && rxtemp != 0xAA) rxcount = 0; // check if first byte is AA
               else rxcount++;
    	}
    }

    But I still wonder where this comes from. No hint found in the errata sheets of the LPC932.

  • hi,

    But I still wonder where this comes from. No hint found in the errata sheets of the LPC932.

    Indeed, so you should look at another end:

    I always send 24 bytes via COM5 (virtual COM port of FTDI232 USB-to-RS232 chip).

    Check this piece. Problem might be in there (you know, win$lows, new drivers, VC++ "features" etc).

    Regards,
    Oleg

  • I always send 24 bytes via COM5 (virtual COM port of FTDI232 USB-to-RS232 chip).

    Check this piece. Problem might be in there (you know, win$lows, new drivers, VC++ "features" etc).


    I guess, I mentioned above that I looked at the signal on RxD input with an oscilloscope (single shot). There was and is no leading zero byte transmitted. When a new interrupt from UART occurs, which should only be initiated by a serial transfer in or out (in this case in) and I can see, with the osci, the first byte is AA, so the SBUF must be overwritten with that byte and the interrupt occured will call the isr to read that byte.

    Let's end this here, the workaround is functioning.

    Thanks for all help.