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
  • That nugget alone is already a very strong hint that your problem is indeed caused by uninitialized variables or lack of volatile qualifiers on variables shared by concurrent threads of execution. Reset state of XRAM may very well be less deterministic than that of RAM cells internal to the chip.
    Ja, aber welche Variablen? Ich benutze für die Datenübertragung die Variable rxcount, das Flag rxflag, die Struktur iobuf und den Pointer char_ptr1. Alles sauber deklariert im Sub-File var.c und var.h.
    Die Daten kommen auch recht sauber und richtig an RxD an, mit Oszi nachgemessen.
    XRAM ist übrigens intern beim LPC932. Das X steht für auxiliary. Deswegen auch XDATA.
    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird, wo soll da was nicht richtig gesetzt oder initialisiert sein?
    Meine Vermutung geht dahin, daß der Keil-Compiler da was nicht richtig macht. Aber bei den vielen Möglichkeiten nehme ich entweder das, was mir am sinnvollsten erscheint oder die default-Einstellungen. Die sollten für das Target LCP932 eigentlich immer passen.
    Leider paßt weder das Memorymodel SMALL noch das LARGE genau auf den Prozessor. Aber ich muß SMALL nehmen, weil bei COMPACT und LARGE der Code >4k wird und da schlägt die 4k-Code-Begrenzung des Compilers zu.

Reply
  • That nugget alone is already a very strong hint that your problem is indeed caused by uninitialized variables or lack of volatile qualifiers on variables shared by concurrent threads of execution. Reset state of XRAM may very well be less deterministic than that of RAM cells internal to the chip.
    Ja, aber welche Variablen? Ich benutze für die Datenübertragung die Variable rxcount, das Flag rxflag, die Struktur iobuf und den Pointer char_ptr1. Alles sauber deklariert im Sub-File var.c und var.h.
    Die Daten kommen auch recht sauber und richtig an RxD an, mit Oszi nachgemessen.
    XRAM ist übrigens intern beim LPC932. Das X steht für auxiliary. Deswegen auch XDATA.
    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird, wo soll da was nicht richtig gesetzt oder initialisiert sein?
    Meine Vermutung geht dahin, daß der Keil-Compiler da was nicht richtig macht. Aber bei den vielen Möglichkeiten nehme ich entweder das, was mir am sinnvollsten erscheint oder die default-Einstellungen. Die sollten für das Target LCP932 eigentlich immer passen.
    Leider paßt weder das Memorymodel SMALL noch das LARGE genau auf den Prozessor. Aber ich muß SMALL nehmen, weil bei COMPACT und LARGE der Code >4k wird und da schlägt die 4k-Code-Begrenzung des Compilers zu.

Children
  • So no variable could "come up 0 or FF". I didn't speak about 0s or FFs, I spoke about the last byte of the transmission somehow wanders at the first byte of the input buffer.
    If you write buffer[offset & ...] as is usually done the difference between 0 and ff would EXACTLY show the phenomen you describe.

    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird, wo soll da was nicht richtig gesetzt oder initialisiert sein?
    only if startup.a51 match your actual situation

    Erik

  • How? A code in a flash ROM can't sometimes run ok and sometimes not
    About 90% of my short time consultings have been to prove that statement wrong.

    Erik

  • So no variable could "come up 0 or FF". I didn't speak about 0s or FFs, I spoke about the last byte of the transmission somehow wanders at the first byte of the input buffer.
    If you write buffer[offset & ...] as is usually done the difference between 0 and ff would EXACTLY show the phenomen you describe.

    I'm not completely sure if I got you correct.
    As you can see in the code example above, it writes to buffer using a pointer. With the first byte coming in from the UART, the pointer is set to the beginning of the I/O buffer structure, the byte is written into it and the byte counter is incremented. Next round the pointer points to the second byte in the I/O buffer and so on. After 24 bytes the byte counter and thus the pointer are reset with the next byte coming in.

    Und wenn der Code dort eine Struktur aufbaut, die anschließend beim Boot-up mit Nullen überschrieben wird, wo soll da was nicht richtig gesetzt oder initialisiert sein? only if startup.a51 match your actual situation.
    As I told before, I have a function which clears the I/O buffer with zeros at startup and after every 24 bytes received.

  • As you can see in the code example above
    unreadable because you did not use pre and /pre
    also, there is no indication what is int and what is char. Int used in both an ISR and main is one of the most "popular" causes of "this proven well working program fails, it can not be my code"

    As I told before, I have a function which clears the I/O buffer with zeros at startup
    What does that achieve if the pointer is wrong when the first char is written.

    Erik

  • As you can see in the code example above
    unreadable because you did not use pre and /pre
    also, there is no indication what is int and what is char. Int used in both an ISR and main is one of the most "popular" causes of "this proven well working program fails, it can not be my code"

    As I told before, I have a function which clears the I/O buffer with zeros at startup
    What does that achieve if the pointer is wrong when the first char is written.

    Erik

  • [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.

  • Sorry, Erik, I don't use this forum very much so I didn't remember that 'pre' thingy. But the code should be readable even on green. ;O)

    About the pointer: I'm not as stupid as I may sound, but when I set a pointer to a certain address BEFORE I write a byte into this address, the pointer can't be wrong.

    We don't speak about a mysterious device with commonly unexpected and unlogical behaviour, we speak about a microcontroller. It has to work, else it's not worth the money.

  • 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.