Serial Driver flush buffer

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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]
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Serial Driver flush buffer

Post 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
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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.
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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?
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Serial Driver flush buffer

Post by Giovanni »

Hi,

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

Giovanni
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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);
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Serial Driver flush buffer

Post 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
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Serial Driver flush buffer

Post 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
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Serial Driver flush buffer

Post 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)
Post Reply