SerialDriver strange loopback

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

Moderator: RoccoMarco

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

Re: SerialDriver strange loopback

Post by Giovanni »

Sorry but that bits of code tells me nothing, I don't know what you are trying to do there.

This is an error for sure:

Code: Select all

chSysLock();
flags = chEvtGetAndClearFlags(&Writer);
chSysUnlock();


Calling a normal API from a critical zone. You should enable the state checker in chconf.h, it finds this kind of errors.

Giovanni
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

Re: SerialDriver strange loopback

Post by steved »

It would probably be simpler to keep the transmit and receive on the same thread, since you can only do one at a time. (In all RS-485 systems I've come across, the default mode is receive, at least as far as the hardware is concerned, with transmit being selected only if you've got something to send). Should give you much better control over sequencing.
enrico.dallavia
Posts: 105
Joined: Thu Mar 12, 2015 10:15 am
Has thanked: 2 times

Re: SerialDriver strange loopback

Post by enrico.dallavia »

Hi Giovanni, thanks for the suggestion. But I've copied the code from here
http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1394
and I did not read any complains about using the code fragment

Code: Select all

 chSysLock();
      flags = chEvtGetAndClearFlags(&elGPSdata);
      chSysUnlock();


So have I to use a standard mutex? Is chEvtGetAndClearFlags thread safe so I can call it without any mutex at all? (I'm just asking because in the post on the link, the author use the chSysLock before call chEvtGetAndClearFlags)

Regarding the suggestion to read and write on the same thread, it is not possible because I have to keep sending data with a fixed and strict throughput, so I prefer to split the send and the receive across two threads.

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

Re: SerialDriver strange loopback

Post by Giovanni »

It is thread safe like all functions without suffix unless the documentation specifies in a different way.

Please read "kernel concepts" in the documentation, name suffixes are related to the system states.

Giovanni
enrico.dallavia
Posts: 105
Joined: Thu Mar 12, 2015 10:15 am
Has thanked: 2 times

Re: SerialDriver strange loopback

Post by enrico.dallavia »

I am really confused, today after reboot the board with stm32 I got the same problem of loopback, I flashed again the same version I saw working yesterday, but still the same bad behaviour. I tried to put reading after writing in the same thread, and still not working :(
So, to know if the buffer over SD2 is empty, is it right to do

Code: Select all

chprintf((BaseSequentialStream*)&SD2,"%s","ABCDEF\n\r"); // write something over SD2
 
  eventflags_t flags;

   do{
        chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));
      chSysLock();
      flags = chEvtGetAndClearFlags(&Writer);
      chSysUnlock();

       if (flags & CHN_OUTPUT_EMPTY) {
          chMtxLock(&mtx);
         chprintf((BaseSequentialStream *)&SD1,"out buffer empty\r\n");
         chMtxUnlock(&mtx);
          break;
       }
   }while(1);


because I must be sure that the transmission is completed, before reset a pin and enable the chip, who translate the UART to rs 485, putting it on reading mode, otherwise I will read what I am currently writing.

I don't belive it, I swear I saw it working yesterday, but today I have a different behaviour.. :roll:
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: SerialDriver strange loopback

Post by Giovanni »

chprintf() is blocking, it does not return until all data have been transmitted, when working with events data should be sent in non blocking mode (TIME_IMMEDIATE) as timeout parameter.

Also, you have again those lock/unlock.

Without a clear picture of what you are trying to do we can just give suggestions about the bits of code you are showing, not about why your program does not work as intended.

Anyway, since you are talking about an RS485 line, I would suggest you look into the UART driver not the Serial driver. The UART driver probably is harder to use (uses callbacks) but it is meant for packet-based protocols like probably you are trying to implement over your RS485. Several users already used it in that scenario.

Giovanni
enrico.dallavia
Posts: 105
Joined: Thu Mar 12, 2015 10:15 am
Has thanked: 2 times

Re: SerialDriver strange loopback

Post by enrico.dallavia »

Ok,
let me explain better, since you are so kind to help me.
I have a board with stm405f (not a developer board but a board manufactured by my company) that has to send some data through rs 485 HALF-DUPLEX. To do that we have connected the pin 2 and pin 3 of GPIOA (configured as uart inside board.h) to a chip that translate the signals to 485. The chip has 1 input pin, where if I put it to 1 with SetPad it can send data if the pin is 0 with ClearPad it can read. The problem I got with the following code, is that I always have as input what I have just written.
If chprintf is a blocking call, it means that the data in the output buffer of SD2, so is there any way that the data are still going out to pin2 gpioA after I clear the pad and put the external chip in reading mode?
The time I got to complete the firmware is almost done, so If possible I want to avoid switching to UART mode, with the chprintf, it worked well (until I have to read commands from serial).
Is chnGetTimeout read from input buffer of SD2 and chprintf write to output buffer of SD2? because I can't explain why I'm reading what I am writing if the chip of 485 is first in writing mode and only after is on reading mode.

Code: Select all

  chMtxLock(&mtxRs485);
  palSetPad(GPIOC, GPIOC_RS485_DE);//put external chip in to writing mode     

  chprintf((BaseSequentialStream*)&SD2,"%s","ABCDEF\n\r");

 
  eventflags_t flags;

   do{
        chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));
      
      flags = chEvtGetAndClearFlags(&Writer);
      
       if (flags & CHN_OUTPUT_EMPTY) {
          chMtxLock(&mtx);
         chprintf((BaseSequentialStream *)&SD1,"out buffer empty\r\n");
         chMtxUnlock(&mtx);
          break;
       }
   }while(1);

   chThdSleepMilliseconds(1000);//wait for test a very big amount of time

   palClearPad(GPIOC, GPIOC_RS485_DE);// put external chip to reading mode     

   chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(40));
   
   flags = chEvtGetAndClearFlags(&Listener);
   
   if (flags & CHN_INPUT_AVAILABLE) {

      chMtxLock(&mtx);
      chprintf((BaseSequentialStream *)&SD1,"Got data to be read\r\n");
      chMtxUnlock(&mtx);

      msg_t charbuf;
      do
      {
         charbuf = chnGetTimeout(&SD2, TIME_IMMEDIATE);
         if ( charbuf != Q_TIMEOUT )
         {
            chMtxLock(&mtx);
            chprintf((BaseSequentialStream *)&SD1,"%c ",(char)charbuf);
            chMtxUnlock(&mtx);
         }
      }while (charbuf != Q_TIMEOUT);

      chMtxLock(&mtx);
      chprintf((BaseSequentialStream *)&SD1,"\r\n");
      chMtxUnlock(&mtx);
   }

  chMtxUnlock(&mtxRs485);


where th events are initialized inside main with

Code: Select all

 chEvtRegister(chnGetEventSource(&SD2),&Listener, EVENT_MASK(1));
  chEvtRegister(chnGetEventSource(&SD2),&Writer, EVENT_MASK(1));
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: SerialDriver strange loopback

Post by Giovanni »

You are doing a basic error, look at this:

Code: Select all

/* Waiting for space into the transmit buffer (CHN_OUTPUT_EMPTY).*/
chEventWait(.....);

/* Switching to TX mode.*/
palSetPad(....);

/* Writing data.*/
chprintf(&SD1, "Hello World");

/* Now data has been written, switching to RX mode.*/
palClearPad(....);


Correct? no...

The Serial driver is buffered, the data is still outgoing AFTER chprintf() returns.

You don't have to wait for CHN_OUTPUT_EMPTY before sending data, you have to wait for CHN_TRANSMISSION_END after the chprintf() return.

Code: Select all

/* Switching to TX mode.*/
palSetPad(....);

/* Writing data, no need to wait for anything.*/
chprintf(&SD1, "Hello World");

/* Waiting for transmission to complete (CHN_TRANSMISSION_END).*/
chEventWait(.....);

/* Now data has been written, switching to RX mode.*/
palClearPad(....);


See the difference?

Giovanni
enrico.dallavia
Posts: 105
Joined: Thu Mar 12, 2015 10:15 am
Has thanked: 2 times

Re: SerialDriver strange loopback

Post by enrico.dallavia »

Sorry to have wasted your time, I've checked with an oscilloscope the signal on the chip MAX1486, I when I write I got the same signal on the input pin! After speaking with the man who developed the board, it told me that it is normal because the loopback is always enabled inside the chip when writing is enabled. I never see something like that and for me it was terribly confusing!
I'm modifying my code and will give you a feedback after this unexpected discovery.

Anyway, thanks again for the suggestions!!
enrico.dallavia
Posts: 105
Joined: Thu Mar 12, 2015 10:15 am
Has thanked: 2 times

Re: SerialDriver strange loopback

Post by enrico.dallavia »

Thank you Giovanni, I can see the difference! Thank you alot!!! you are the lifesaver of my drowning life today.
Post Reply