Page 2 of 3

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 3:01 pm
by vrollei
Hi, Giovanni,

thanks for reply, but I need extra help.
There are 2 threads concurrently writing to the log, after several calls logger waits forever for transmission end event.

Logger code:

[font=Courier New]void logInit(SerialConfig *sdConfig) {
if (logInited == false) {
logInited = true;
sdConf = sdConfig;
chMtxObjectInit(&logMtx);
chEvtRegisterMaskWithFlags(&(LOG_SD.event), &logListener, EVENT_MASK(0),
CHN_TRANSMISSION_END);
}
}

bool logLock(void) {
if (logInited) {
chMtxLock(&logMtx);
chEvtGetAndClearFlags(&logListener);
sdStart(&LOG_SD, sdConf);
return true;
} else {
return false;
}
}

void logUnlock(void) {
do {
chEvtWaitOne(EVENT_MASK(0));
} while ((chEvtGetAndClearFlags(&logListener) & CHN_TRANSMISSION_END ) == 0);
sdStop(&LOG_SD);
chMtxUnlock(&logMtx);
}


#define debug(FRM, args...) { \
if (logLock()) { \
const char *A[] = {FRM}; \
chprintf(__LOG_STREAM, "%s:%d - ", __FILE__, __LINE__);\
if(sizeof(A) > 0) {\
chprintf(__LOG_STREAM, *A, ##args); \
chprintf(__LOG_STREAM, "\r\n"); \
} else {\
chprintf(__LOG_STREAM, "\r\n"); \
}\
logUnlock(); \
} \
}[/font]

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 4:23 pm
by Giovanni
Are assertions and state checker enabled?

The mutex is supposed to be released by the same thread that took it.

I suggest this procedure:

1) Lock
2) Clear
3) Write
4) Wait
5) Unlock

Giovanni

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 4:34 pm
by vrollei
Assertions and checks are enabled in chconf.h.

The mutex is released by the same thread as well: any thread calls debug macro and mutex lock/unlock inside this macro.

And procedure implemented exactly to your suggestion, except sdStart/sdStop.

I tried to call chEvtGetAndClearFlags before and after sdStart, the result was the same.

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 5:51 pm
by vrollei
The problem is related to event. Logger works fine without event processing.
Is it possible to miss CHN_TRANSMISSION_END event if SD ends transmission before chEvtWaitOne is called?

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 7:17 pm
by Giovanni
Hi,

No, the event is buffered (it is a flag) and chEvtWait() will exit immediately on call.

Giovanni

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 8:30 pm
by vrollei
Hi,

some additional information

during second call (second thread write to log) of chEntWaitAny system goes to _idle_thread and never exit from it.
Call trace:
logUnlock()
chEvtWaitAny
chSchGoSleepS(CH_STATE_WTOREVT);
chSysSwitch(currp, otp);

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 8:45 pm
by Giovanni
It looks like the event is not generated or does not triggers the thread, I suggest putting breakpoints in relevant code parts, starting from the serial driver ISR. Make sure to compile using -O0 while debugging.

Giovanni

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 10:26 pm
by Giovanni
Thinking again, what is your use case exactly? maybe you should consider the use of the UART driver, it has a function named uartSendFullTimeout() that returns on full transmission.

Giovanni

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 10:53 pm
by vrollei
Hi,

I am trying to implement simple logger to use it with low power sleep mode.
So I need to stop SD after transmission of log message finished, this will allow power driver to activate low power sleep mode.

Scenario:

1. Program calls logger, e.g. debug("test message")
2. Logger locks mutex to prevent mess in log messages and several calls of sdStart
3. Logger starts SD and writes log message using chprintf
4. Waiting transmission complete
5. Logger stops SD and unlock mutex

Re: Serial Driver flush buffer

Posted: Tue Mar 21, 2017 11:07 pm
by vrollei
Is this valid scenario:

Thread A calls chEvtRegisterMaskWithFlags(&LOG_SD.event, &logListener, EVENT_MASK(0), CHN_TRANSMISSION_END) to register listener
Thread B calls chEvtWaitAny(EVENT_MASK(0)) and chEvtGetAndClearFlags(&logListener)