ChibiOS Event listener losing data - Page 1
Forum section: electronics / general

author: Torrentula
author_rank: Regular Contributor
timestamp: September 05, 2013, 12:08:52 pm
content: Hello ChibiOS users!I'm currently trying to read NMEA data from a GPS module (9600 baud 8N1) and have some trouble reading the data correctly. It seems that I am losing data from the serial port and I don't know why. My event listener thread looks like this:Code:static msg_t Thread6(void *arg){(void)arg;chRegSetThreadName("GPSdata");// Activates the Serial driver 2, PA2(TX) and PA3(RX) are routed to USART2, 9600 8N1.palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));sdStart(&SD2, NULL);EventListener elGPSdata;flagsmask_t flags;chEvtRegisterMask((EventSource *)chnGetEventSource(&SD2), &elGPSdata, EVENT_MASK(1));while (TRUE){chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));chSysLock();flags = chEvtGetAndClearFlagsI(&elGPSdata);chSysUnlock();if ( flags & 128 ){chprintf((BaseSequentialStream*)&SDU1, "%c", chnGetTimeout(&SD2, TIME_IMMEDIATE));}}return 0;}As you can see I'm currently just reading the data from serial port 2 (USART2) one character at a time as soon as an event fires.I'm a bit lost when it comes to the ChibiOS documentation as I have no idea how to really check what the value of flags should be when there is a character available. The value of 128 I got by observation (printing flags along with read character).If this is because I don't understand the fundamental concepts of the events in ChibiOS then please feel free to educate me...(BTW I couldn't register in the ChibiOS support forum, otherwise I would've asked there)

author: andyturk
author_rank: Frequent Contributor
timestamp: September 05, 2013, 03:34:33 pm
content: You should figure out how to register on the ChibiOS forum because Giovanni could probably point out the issue with your code in five minutes. He's very helpful with those kinds of things.I haven't used events with serial drivers, but here's a thought... It could be that the serial driver's internal buffer is overflowing because your code doesn't read all the available data each time it gets an event notification. I.e., you're only reading one character, but there may be more in the driver's buffer.BTW, is there a reason you're not using chSequentialStreamGet(BaseSequentialStream *)? It returns a single character from the driver's buffer and blocks the calling thread if there's no data.Code:static msg_t Thread6(void *arg){(void)arg;chRegSetThreadName("GPSdata");// Activates the Serial driver 2, PA2(TX) and PA3(RX) are routed to USART2, 9600 8N1.palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));sdStart(&SD2, NULL);while (TRUE){char c = chSequentialStreamGet(&SD2);chprintf((BaseSequentialStream *) &SDU1, "%c", c);}return 0;}

author: mrflibble
author_rank: Super Contributor
timestamp: September 06, 2013, 07:53:39 am
content: Also, shouldn't you be usingchEvtGetAndClearFlagsinstead ofchEvtGetAndClearFlagsI? Since you are using it from a loop in a thread, as opposed to an interrupt handler.

author: Torrentula
author_rank: Regular Contributor
timestamp: September 07, 2013, 07:52:35 am
content: QuoteYes I should, corrected.Okay I finally managed to register on the ChibiOS forum and sure enough Giovanni provided help, almost instantlyHere is the code if anyone is interested:Code:static msg_t Thread6(void *arg){(void)arg;chRegSetThreadName("GPSdata");// Activates the Serial driver 2, PA2(TX) and PA3(RX) are routed to USART2, 9600 8N1.palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));sdStart(&SD2, NULL);EventListener elGPSdata;flagsmask_t flags;chEvtRegisterMask((EventSource *)chnGetEventSource(&SD2), &elGPSdata, EVENT_MASK(1));while (TRUE){chEvtWaitOneTimeout(EVENT_MASK(1), MS2ST(10));chSysLock();flags = chEvtGetAndClearFlags(&elGPSdata);chSysUnlock();if (flags & CHN_INPUT_AVAILABLE){msg_t charbuf;do{charbuf = chnGetTimeout(&SD2, TIME_IMMEDIATE);if ( charbuf != Q_TIMEOUT ){chprintf((BaseSequentialStream*)&SDU1, "%c", (char)charbuf);}}while (charbuf != Q_TIMEOUT);}}return 0;}The if-statement in the do-while loop just prevents the Q_TIMEOUT flag being printed to the debug output.