[DONE] Serial port losing data when several threads are acti

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

hebnern
Posts: 7
Joined: Sat Jun 15, 2013 4:06 am

Re: Serial port losing data when several threads are active

Post by hebnern »

Yes, the onewire spec requires a 4.7k pullup. I am using a 5k since thats what I had lying around.
trepidacious
Posts: 58
Joined: Mon Jan 21, 2013 3:36 pm
Been thanked: 1 time

Re: Serial port losing data when several threads are active

Post by trepidacious »

I've been having a look at 1-wire using the serial driver, by adapting the code from here:
http://forum.chibios.org/phpbb/viewtopic.php?f=8&t=713

I ported that code to 2.6.1, and it works well, but I'm also having trouble using the serial driver, I've tried the same sdPut/sdGet approach, as well as chSequentialStreamWrite/Read, they both seem to hang on receiving data. sdPut/sdGet will sometimes make it through a whole transaction, and I get some reasonable looking data back, but with an incorrect CRC which makes me think something else is wrong. However if I perform a few transactions, eventually it will hang on sdGet. This is with no other threads running, with serial access from the main thread via a shell command.

I'm not completely sure how I should be using the serial driver, so I may well have something misconfigured.

My reason for using the serial driver is that I've run out of DMA streams due to the DCMI problem on STM32F407. While my 1-wire test is not using any other threads, I intend to use the 1-wire driver on another project where there is much more going on.

I can make the code available if that helps.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Serial port losing data when several threads are active

Post by Giovanni »

Hi,

Do you handle transmission errors and the case where some data is lost? if you wait for a fixed number of bytes and some is lost because an error then the code would wait for more data that will never be sent.

It is just an hypothesis of course, it all depends on your code. In general:

If you send/receive a fixed amount of data without delimiters you have to handle the case where the number of received bytes is different from what you expect. This can be done using timeouts for example.

It is a good idea to frame your data with delimiters, text lines for example, this way you just wait for the delimiter, regardless the lenght of the data in the frame. This makes easier to resynchronize with the data flow in case of errors.

Giovanni
trepidacious
Posts: 58
Joined: Mon Jan 21, 2013 3:36 pm
Been thanked: 1 time

Re: Serial port losing data when several threads are active

Post by trepidacious »

Hi,

Thanks, I'm now using sdGetTimeout, and I'm seeing random timeouts, sometimes none in a transaction, usually a timeout every 10 or so bytes. The data that I DO get looks more or less right, but not quite perfect even when I get no timeouts.

For normal serial use I agree I would normally use a timeout and delimiters to allow for errors. However in this case I was expecting to know exactly what I would receive, since the UART is configured for open drain half-duplex to work with 1-wire, so it should always see its own start bits, and so always receive one byte back per byte sent (often the same byte, but the 1-wire device can pull the line low during the data bits to return data).

If I use code like:

Code: Select all

    
    sdPut(drv->config.uartd, *send_buf);
    r = sdGetTimeout(drv->config.uartd, MS2ST(10));


am I guaranteed to see each transmitted byte received back again? Is there any way for the byte to be transmitted before the uart is ready to receive? I assume it is receiving as long as the serial devices is started with sdStart?

I've done some more testing with the UART driver, where I can use:

Code: Select all

  uartStartReceive(drv->config.uartd, len , receive_buf);
  uartStartSend(drv->config.uartd, len, send_buf);


and this seems very reliable.

Thanks,
Ben.
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Serial port losing data when several threads are active

Post by Giovanni »

Hi,

Do you listen for errors using an event? it would be useful to know if you are getting framing or parity errors too. Timeouts could be just a consequence of errors in the stream.

Giovanni
trepidacious
Posts: 58
Joined: Mon Jan 21, 2013 3:36 pm
Been thanked: 1 time

Re: Serial port losing data when several threads are active

Post by trepidacious »

Hi,

I've added an event listener for the errors, looks like all I get is an SD_NOISE_ERROR when doing the "one wire reset" part of the comms. I guess this is because the one-wire devices pull the line low at an unexpected time, however they should always set at least one bit low, so I think this can be ignored.

I did find one definite error in my code - with the uart driver, it's easy to ignore received data by just using uartStartSend with no preceding uartStartReceive. When I adapted this, I forgot to make sure to clear this received data with sdGet, when performing a send rather than a transfer. Fixing this seems to fix everything, although I'm really not sure how I was getting timeouts before. I don't seem to be getting them now, but they went away BEFORE I fixed the code, so this might be a signal problem still. At least I can watch out for any errors with events and timeouts, thanks for the help debugging!

Ben.
trepidacious
Posts: 58
Joined: Mon Jan 21, 2013 3:36 pm
Been thanked: 1 time

Re: Serial port losing data when several threads are active

Post by trepidacious »

I don't know whether this is the real cause of the problems, but I've worked out what changed to get rid of the timeouts - if I have an event listener registered on the serial driver, and I call chEvtWaitOneTimeout on it in a loop, I get reliable comms. If I don't run the thread with that loop, I get many timeouts. If I make that thread just loop with a 10ms sleep, I still get the timeouts. It doesn't seem to be necessary to even "get" the flags - previously I was using chEvtGetAndClearFlags and then printing any errors to USB serial, but I've removed that and comms still run fine.

Is it mandatory to use the event listener for comms to work, or is this just a symptom of some other bug in my code I've not found yet? :)
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Serial port losing data when several threads are active

Post by Giovanni »

It is not mandatory if you are not interested in errors. I think there is something in the code :) do you implement a state machine for your protocol? if so, is it correctly implemented?

Giovanni
trepidacious
Posts: 58
Joined: Mon Jan 21, 2013 3:36 pm
Been thanked: 1 time

Re: Serial port losing data when several threads are active

Post by trepidacious »

The protocol is quite simple, so no state machine is needed to give a synchronous interface to 1-wire devices. Each transaction with a 1-wire device just consists of a series of bytes sent by the MCU in half duplex mode, so that the MCU receives back every byte it sends. If the 1-wire device is expected to be "sending" data then the byte received by the MCU is checked against the byte it sent, and any changes are due to the 1-wire device pulling the half-duplex line low during the byte. Everything is driven by the MCU, so there's no need to respond to comms initiated by the device, so I don't really need events at all (except to check for errors, which I'm not seeing any more after enabling one-bit mode to ignore noise errors).

Just in case there is anything obvious (or anyone wants to use the code), here's a zip of the project https://www.dropbox.com/s/jf5q7vakvb7ket3/discovery-serial-1wire.tar.gz - it's basically just the same code from this thread http://forum.chibios.org/phpbb/viewtopic.php?f=8&t=713 but with an added driver for the MAX31826, and a define to switch from UART driver to serial driver (currently set to true). The only interesting code is in oneWire.c/h, in the transfer() and send() functions, which just call sdPut() and sdGetTimeout(), and in main.c in the serial_event_thread() function. If that thread is started, everything works fine, otherwise serial comms time out. It should all work fine on a discovery board with nothing connected except a 5K pullup on PD8, running "ow maxsingle" will try to talk to a 1-wire device, this will cause a large number of timeouts if the event listener is not running. If the event listener is running, the serial communications will work fine (obviously the transaction as a whole will fail - the shell will print a message about a bad CRC since there was no device to actually send back data).
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Serial port losing data when several threads are active

Post by Giovanni »

Have you considered the use of the UART driver instead? being based on callbacks would make the implementation of a state machine easier, virtual timers could be used for timeouts if you need them.

Giovanni
Post Reply