Re: xPC Serial Communication Problems



Walter,

Look at the large subsystem blocks under the 'Mainboard' section.
I really need to reorganize this part of the library to make it
less confusing.

Because each subsystem includes the ISR needed to handle the
interrupt, you need a separate one for each IRQ. You can configure
the mainboard subsystem block to work with COM1 alone, COM1 + COM3
(since they share an interrupt usually) or COM3 alone, or as COM2,
COM2+COM4, or COM4. If you set it to COM1, then you still need to
connect a ground and terminator to the other pair to satisfy Simulink.

The FIFO read blocks are only for use with the new subsystem blocks.
They won't work with the old blocks. There are two versions of the
subsystem blocks. One has the simple fifo read inside it, the other
brings the FIFO signal out where you can connect any one of the 3
fifo read blocks to it. Each one looks at the character stream
slightly differently. The basic FIFO read block can read a fixed
length binary string or a terminated ascii string. It never throws
any characters away so it may return more or less than you expect if
it gets out of sync.

The other two fifo read blocks can look for patterns and throw away
characters that don't match one of a set of patterns. The binary
read headers block looks for a binary pattern to start a message, then
copies a fixed length after that to the output. The ascii version
also looks for a header, but then copies up to a single or multiple
character termination string. The binary read headers block is similar
in function to how you describe the device you're sending to, but it
can look for several different headers and direct them to their own
output port. On a given time step, if a complete new message matching
the pattern isn't found, then the output will be a vector with null
contents. If the first element is 0, then the string is null length
inside a larger vector.

Since you describe sending, you can just use the subsystem that has
the fifo read inside it and just connect the output to a terminator.

Gordon Weast
xPC Target Development
The Mathworks


Walter Collins wrote:

Gordon,

I had looked into the possibility of upgrading to the newer blocks,
but I'm a bit lost. We're running version 2006a and all of the actual
serial communication blocks (that aren't marked "not for new models")
seem to be written for specific add-on serial port/communications
boards. I don't see a single one for using the serial ports that come
on a CPU card. We're using the serial ports that come on the CPU
board since we don't have room to add an extra PC-104 card to the
stack (and it has 2 ports on it, which is all we need). Did I miss
some documentation somewhere on how to upgrade from the older blocks
to the newer ones in the instance we're in? Looking over the FIFOs
with the advice you posted makes me think I can use those just fine
to implement what we're doing in the old code, but I'm stumped as to
what I should be doing as far as connecting those FIFOs to the
onboard serial ports.

Thanks for all the help you've given.
Walter

Gordon Weast wrote:


Walter,

The older serial block you're using uses the kernel resident driver
and I don't have much control of that.

The newer component version runs entirely in Simulink code. I've
never seen bytes get wrapped like you're seeing with the new
driver.
The data you send needs to be formatted slightly different for the
new driver. Since you have data bytes that have the value 0, you
need to present the data as a vector of 16 bit values. Only the
bottom 8 bits are sent, just leave the upper 8 bits empty. The
first element is the number of values to follow. So, with the
old driver you would have the vector:

[0xBA 0xBD 0xBD 0xBA 0xBA 0xBD 0 7 255 7 255 7 255 0 0] as a uint8
vector,

with the new driver you would change this to:

[15 0xBA 0xBD 0xBD 0xBA 0xBA 0xBD 0 7 255 7 255 7 255 0 0] as a
uint16
vector.

The new driver interprets a uint8 vector as a null terminated
string,
so it would take the first vector and just send the 6 byte header
and
stop before sending the 0. The uint8 vector format is therefore
only
useful for true ascii strings that don't contain 0 data bytes.

You will get a lot more control with the new driver. I've never
seen
it send bytes out of order or a message get rotated like you're
seeing.

Gordon Weast
xPC Target Development
The Mathworks


Walter Collins wrote:


I'll start with the oscilloscope, since that's what we used to
discover this problem and because the only reason I mentioned

the

receiving system was that that system can't handle the packets
becoming lopsided like this. I'll describe that system in more

detail

later, just in case you think it might be useful.

We did hook an o'scope up to the transmit line coming out of

the

target PC. This confirmed that when we saw strange behavior on

the

console, the packets coming from the target PC are still 15

bytes

long, 115.2 kbps, etc. The only difference is that it was if

we'd

rotated the packet structure so that we had 1, 2 or 3 data

bytes

at

the beginning of it, then the 6 synch bytes, then the remainder

of

the data bytes. Everything about the packet looks just fine,

other

than being "rotated" like this. That's why I put forth my guess

that

somehow we either lose a byte or add a byte or something in the
serial routines on the target computer. The "beginning" of the

packet

doesn't always look the same due to this packet rotation. The

only

other thing I can think to add is that the CPU uses a 16550 (or

some

reasonable facsimile) so the hardware buffer should be 16

bytes.

Packet should be:
BA BD BD BA BA BD 0 7 255 7 255 7 255 0 0

Packet ends up something like:
255 0 0 BA BD BD BA BA BD 0 7 255 7 255 7

(with very large gaps between packets so it's easy to see that

we're

looking at a packet)

The console is an embedded microcontroller running homebrew C

code.

The serial port doesn't have any hardware buffer so I have an
interrupt reading it after every byte and the interrupt's high

enough

priority that it doesn't get interrupted itself. I drop the

bytes

into a ring buffer and then "look backwards" to see if the

synch

bytes are "in position" and if they are, then I know I've

received

the whole packet and I pass it along to the main loop. The ring
buffer's currently 16 bytes and we've verified that it can't

get

a

false positive on the synch byte check. I could modify its code
slightly so as to double buffer the data and this *should*

avoid

the

console going crazy when this packet shifting takes place, but

it

doesn't solve the source of the packet shifting. It would,

however,

mean that we might be lagging by 50 ms as we wait for the tail

end of

a packet to come in. In the current use, that 50 ms is probably
acceptable, but this may not always be the case. Hopefully this
answers all of your questions.

Walter

Gordon Weast wrote:


Walter,

I'll ask a few questions about your system before making a

guess

about what's going on here.

Is the receiving machine executing at the 'same' 50 ms rate?
I quote the word 'same' since any such attempt will always

result

in drift between the two machines unless something forces

them

to stay synchronized.

Is the receiving machine using a read call to its system

that can

return exactly 15, or merely up to 15 characters at a time?

That

is,
does it wait until there are at least 15 characters in the

receive

buffer, then return exactly the first 15, or does it return
whatever
is in it's buffer, up to 15 characters?

Does the receiver throw away characters until it sees the

sync

characters,
then read the fixed message length? This will force
synchronization,
even when the reader executes when a partial message has

been

received.
A partial message could be in the receive buffer if the two
machines
execute with the right phase shift (receiver looks at the

buffer

when
a message is partially done).

I suspect you're seeing a timing drift problem, but I can't

be

sure.

If you connect an oscilloscope to the transmit data wire and
measure
the data burst, is it 15 characters long at 115200 baud?

With 8

data
bits, plus start and stop, there are 10 bits per character

so

this

data rate is 15*10/115200 = 1.302 ms. Is it always this

length

with the
beginning always looking the same? If so, then you're seeing

a

receive
synchronization problem.

Gordon Weast
xPC Target Development
The Mathworks

Walter Collins wrote:



I'm using RTW with the xPC target to send data from the

target

computer to a control console. The data is 15 bytes long

and

gets


sent every 50 ms (20Hz). The model on the target

computer

currently


consists of 5 constant source blocks (split off into 15

lines)

going


into a pack block that's expecting 15 uint8's and this

is fed

into a


binary serial send block. The serial send block's

message width

is 15


with a sample time of 0.05. The rs232 set-up block sets

the

port


up


to be 115.2 kbps with Tx and Rx buffer sizes of 1024, no

parity,


8


data, 1 stop, no protocol.

With that out of the way, the problem is this. The code

works

just


fine for a while. The packet has 6 "synch" bytes at the

beginning,


followed by a combination of 0, 255 and 7. Monitoring

the

serial


stream coming from the target computer, we can clearly

see each

of


these where we expect them. After some random amount of

time,

however, the serial stream changes. The bytes seem to be

the

right


bytes, but now they're out of order. It's as if we lost

some

bytes or


added some at some point. Now we'll have some of the

data bytes

(the


0, 255, 7) at the beginning of the 15 byte packets,

followed by

the


sync bytes, follewed by the rest of the data. This is

causing

havoc


on the receiving end, which relies on there being a bit

of

breathing


room at the end of a packet. Since the packets are now

split

between


packet trasmissions, we don't have that breathing room.

Has anyone else seen this or have any recommendations on

how to

fix


it? I've tried looking through the Simulink code for the

serial

blocks, but they just refer to "functions imported from

the

kernel"


so I can't see how they're actually handling the serial

communication


on a low level.

Thanks in advance for any help,
Walter

.



Relevant Pages

  • Re: When to FIFO
    ... always use a FIFO. ... the digital domains that operate at different clock rates. ... DAC with internal interpolation/quadrature modulation blocks. ... With long lines -- up to 132 characters -- the scanning element needed up to 12 character times to begin a new line, all the while accepting new characters at the input. ...
    (comp.dsp)
  • Re: xpc target communicating mismatch
    ... If I connet to XMT1, when running the model, the error message shows up: Input port width is less than the input count. ... The obsolete RS232 binary send/receive block doesn't output a ... FIFO signal so when you try to connect it to the FIFO read block, ... header and enough characters to fulfill the read. ...
    (comp.soft-sys.matlab)
  • Re: xpc target communicating mismatch
    ... FIFO bin read is one dimensional vector with 2 elements. ... You need to synchronize on some part of the message that is invariant. ... header and enough characters to fulfill the read. ...
    (comp.soft-sys.matlab)
  • Re: [PATCH: 2/2] [SERIAL] avoid stalling suspend if serial port wont drain
    ... prefer - the system being prevented from suspending and losing complete ... The only way you could do that on 8250 is to clear the RX FIFO, ... wait for the port to transmit all its characters into the RX ...
    (Linux-Kernel)