Potential bug in pspDebugSioSetBaud ?

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

Potential bug in pspDebugSioSetBaud ?

Post by makai »

I've discovered an interesting phenomenon while compiling the LUA v0.20 player code.

Since I ran into the problem of lost characters when calling sioRead() in LUA at every baud rate, I have recompiled the LUA source without the call to pspDebugSioSetBaud() that is normally executed within LUA's sioInit().

Interestingly, when pspDebugSioSetBaud() is NOT called, the LUA command works fine (entire string is received). However, when pspDebugSioSetBaud(4800) is called (note that the baud rate is left unchanged from it's default), the situation changes and only the first character is returned by the LUA call to sioRead().

To make things short: Initializing the serial port without calling baud rate adjustment delivers the expected result. As soon as the baud rate command is touched, the character delay/truncated transmission phenomenon is encountered.

I suspect there is a problem in pspDebugSioSetBaud(). Can anyone confirm this?
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

To illustrate the setBaudBug

Post by makai »

If you'd like to test it out yourself, download the zip file below. It contains two versions of the LUA player, one compiled with the call to pspDebugSioSetBaud(4800) and one without. Read the Howto.txt file included in the archive.

www.essentializer.com/BugInSetBaud.zip
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

There are other reasons why the serial port plays up in LUA.
I have spoken to Shine about this.
The same routine to recieve serial comms in C doesn't work in LUA.
It's very slow, and loses bytes in the transmission.
The only way I achieved good comms was to force the sending station to
send one byte at a time (like a Human tapping on a terminal keyboard)
with a big delay inbetween.
The serial FIFO buffer doesn't seem to work at all in LUA.
Art.
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

Aware of that

Post by makai »

I'm aware of your delay circuit and I know that this is one way to fix the problem. But how do you explain that the LUA code actually works fine (without delaying the characters) when pspDebugSioSetBaud is never called?

When the serial port is opened, it's set to 4800 baud. If the port is opened without a call to pspDebugSioSetBaud the FIFO buffer works fine! Try out my code attached to my previous post to see for yourself.

However, even when pspDebugSioSetBaud is called with 4800 as parameter, the FIFO breaks. Technically we should not be changing any registers with this call, since it corresponds to the initial baud rate....

Get my point?
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Yes got it that time, I can't read.
Pity I didn't know that, I could have set the GPS mouse to send at 4800 baud.
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

You could have..

Post by makai »

Yes, you could have but only when using the modified LUA version. 4800 baud without 15 ms character delay is still faster than 38400 baud with 15 ms character spacing.

I'm sure the same thing happens in C as long as PSPSDK is used. I'll try to write a minimal code snippet to demonstrate the effect in C++.

What I think is happening is that setBaud messes up timing registers to some extent and the FIFO buffer get's garbled. So if you send "Hello", the FIFO might look like this: H****l**l*****o, where * denotes an invalid character that will return -1 on read. First read loop might return "H" only. The next time read is executed, the buffer might look like this: **l******o****, thus the first "l" was pushed out of the FIFO by the garbled chars and we'll end up with an incomplete transmission.

So what I'll try to prove the effect is this (pseudo code):

Code: Select all

initializeSerial()

// Execute twice: Once before call to setBaud and once after
for i=0 to 1
{  
  wait for button press{
    // let user send a string to the FIFO (e.g. "Hello") and have 
    // him/her press a button when done
  }

  // Expect to print "Hello" on first (i==0) run
  // and garbled text on second run, after setBaudRate has 
  // been called below
  do{
    ch = readChar()
    print(ch)
  }
  while(ch !=-1)

  setBaudRate(4800) // According to my theory, this will scew up the FIFO
}        
I'll let you know when I'm done with the C-example.
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

C-Example program to demonstrate setBaud() bug

Post by makai »

OK, I'm done writing the example program to demonstrate the bug in pspDebugSioSetBaud(). Guess what? It's exactly as I said. Serial input works fine as long as setBaud is not called. This holds true for all applications based on the PSPSDK, inlcuding LUA.

Get the example application below and see for yourself. Let me see how I can report that bug to our PSPSDK dev team...

http://www.essentializer.com/setBaudBug.zip
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Your code is definitely relying on the FIFO. Another, usually better way to handle the input would be to set up a serial interrupt and read each byte as it's received. However, that still doesn't explain why the fifo is disabled, and I don't see a reason for it either. If you check the pspDebugSioSetBaud() source it only writes the baudrate to the DIV1 and DIV2 registers, and 0x60 to the CTRL register. The uart4.prx code also writes 0x60 to the CTRL register, but hpremote.prx uses 0x70 instead -- but I tested 0x70 and that doesn't seem to change the results. I also tried to send the full init sequence that hpremote.prx uses, with no difference.

So my suggestion for now would be to use interrupts (see psplink sio) or look deeper into sony's prxes and figure out what we're doing wrong.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Ahem...

Code: Select all

		pspDebugSioInit();
    		pspDebugSioSetBaud(9600);
I'm still reading in strings of up to 15 characters sent at 9600 baud
straight from the barcode acanner: http://www.youtube.com/watch?v=ZO7HENwIvPs
What's the difference between SetBaud and DebugSetBaud?

Or is my program just returning to read the serial port often enough
so that it doesn't miss any characters?
Art.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

SetBaud of course works, tons of programs use it. You and all of the other working programs are most likely reading characters often enough. makai's code is a bit strange in that he just sits there waiting for the FIFO to fill and then finds out that it only was one character deep. I don't know why SetBaud seems to put the serial port in that mode.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Fair enough.
There is an obvious drawback in that method as well in that the serial
recieving routine ends up ruling the whole program, with no time for
screen updates, etc. while waiting for a possible transmission.

I have a feeling Deniska is working that way in his mapping program,
since the screen wouldn't need to be updated until a new NMEA sentence
is recieved from the GPS unit.
makai
Posts: 7
Joined: Tue Jun 26, 2007 7:50 pm

Post by makai »

Well, of course I'd prefer the interupt version for serial reads. But I don't see how this could be integrated into LUA, which is definitely a drawback.

In MapThis it doesn't make a big difference, since updates are relatively slow. I'm working on an application where data is continuosly sent at 38400 baud with about 1 kbyte per second. So constantly polling due to a non-working FIFO is not an option and interrupt based sioReads() will force me to port my code from LUA to C++ (and it's a LOT of LUA code...)

As I said before: I don't think that data acutally gets lost, since constant polling always return all characters.

My theory is that the FIFO buffer is constantly filled with invalid data between valid characters (remember the H****l***l***o example in my post above) and as soon as an invalid "*" character is encountered, sioRead() returns -1. Now if you keep polling, you will eventually get the rest of the characters. But if you continue reading only after a delay, the invalid characters constantly entering the buffer will gradually kick out the valid chars. This may explain why at times you end up with "H" only, sometimes also "Hl" or "Hlo", depending on how long you wait between subsequent reads. Again, this is only a theory...

Is there a way to compare the serial registers before and after the call to pspDebugSioSetBaud()? I'm not really familiar with C, I usually code in Java...
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Art wrote:Fair enough.
There is an obvious drawback in that method as well in that the serial
recieving routine ends up ruling the whole program, with no time for
screen updates, etc. while waiting for a possible transmission.

I have a feeling Deniska is working that way in his mapping program,
since the screen wouldn't need to be updated until a new NMEA sentence
is recieved from the GPS unit.
MapThis uses the serial port interrupt.
Post Reply