Page 2 of 4
Re: SerialDriver strange loopback
Posted: Tue Mar 31, 2015 5:00 pm
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
Re: SerialDriver strange loopback
Posted: Tue Mar 31, 2015 8:05 pm
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.
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 1:41 pm
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=1394and 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
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 2:11 pm
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
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 2:54 pm
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..

Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 3:13 pm
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
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 3:46 pm
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));
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 4:04 pm
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
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 4:33 pm
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!!
Re: SerialDriver strange loopback
Posted: Wed Apr 01, 2015 4:38 pm
by enrico.dallavia
Thank you Giovanni, I can see the difference! Thank you alot!!! you are the lifesaver of my drowning life today.