Dual-UART-USB Monitor problem

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

Moderator: RoccoMarco

Post Reply
Astralix
Posts: 5
Joined: Tue Sep 16, 2014 4:25 pm

Dual-UART-USB Monitor problem

Post by Astralix »

Hi all,

First of all, I am not new to embedded and not new to STM32 programming. But this is my first Chibios project on an STM32.
I have most of the available STM32 dev kits but with Chibios I could only get the STm32F4-DISCOVERY to start a USB-CDC device successfully. This is no problem so far.

The intended project is very simple: I often work with embedded controllers that communicate via UART. But these system do not use standard baud rates or accept bigger baud rate errors than a standard USB dongle accepts. In my current case I have to AVRs talking at 250kBaud and my CP2101 USB UART dongle refuses to run on that speed. But if I go down to 115200Baud the AVRs have -8% error as both are equipped with straight crystals (2MHz / 8Mhz) which again causes only erratic characters.
The code is available here: https://github.com/Astralix/chibios-dualport-monitor

I copied the STM32F4-DISCOVERY-MEMS project as a starting point and threw out the MEMS, but kept the USB-CDC UART implementation. Then I added UART2 and UART3.
Then I do two unblocking ansynchronous reads to the serial port devices and copy the read content to the USB-CDC with a blocking write:

Code: Select all

/* Non blocking read from RX channel 2 */
   cbuf2 = sdAsynchronousRead(&SD2, buf2, RX_BUF_SZ);
   if (cbuf2) {
      palSetPad(PORT_LED_GREEN, PIN_LED_GREEN);
      cbuf2 = filter( (char*)tx_buf, (char*)buf2, cbuf2);

      sdWrite(&SDU1, tx_buf, cbuf2);
   }

After that the same is done for USART3 and the red LED.

This code resides in the main() while(1) loop followed by a chThdSleepMilliseconds(10);

The 10ms delay was chosen based on the following calculation:

250kBaud will result in approx. 25000 chars per second. Scanning the input buffers with 100Hz will give a maximum of 250 characters in the buffer. 250 characters can easily be passed and filtered and then put through the USB interface.

This pretty much works... but then it suddenly stops working. What I can see is, that the LED of one channel is lit but the system itself hangs after that. I have a blinking task running, and this task is hanging too in the most times, sometimes it still is blinking. The USB connection is thrown most times too.

So, I do not have set up much for debugging. I am using arm-none-eabi gcc toolchain 4.8.2 in ubuntu 14.04 with openocd 0.8.0 working fine with latest stlink-v2 on the discovery board.

Before trying to install lots of things, I would like to know if there are obvious pitfalls in my code regarding the way I am using the UARTs and the USB. I am pretty sure I misunderstood something as I am new to Chibios.

I know that the code has some bugs regarding the USB handling as it allows to write data to the USB even it is not connected. But this is not the reason for the crash and I fix it asap.

Thanks in advance for any helping hand
Astralix
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dual-UART-USB Monitor problem

Post by Giovanni »

Hi,

Some suggestions:

1) Enable the debug options in chconf.h, those can catch a lot of errors and stop the system if something is detected, then using the debugger you can examined the string pointed by dbg_panic_error and see the stack trace in order to understand what failed.

2) Do not assume you will always receive the number of chars you expect from the UART, sdAsynchronousRead() will wait until the exact number of chars is received, this may not be true in case of receive errors, you may consider using a receive timeout there.

3) There is no need to insert those 10mS sleeps, both the USB_SERIAL and the serial driver are able to broadcast events, you may just create one big loop where you wait for one of the events and then do the transfers.

Also, you need debug capability if you plan to do complex things. You may try chibistudio, it includes everything is required.

Giovanni
Astralix
Posts: 5
Joined: Tue Sep 16, 2014 4:25 pm

Re: Dual-UART-USB Monitor problem

Post by Astralix »

Hi Giovanni, thank you for your reply!

Is I thought, there are probably mistakes and misunderstandings from me...

I'll try installing the Studio, sure. Thanks for the hint, I just flew over the comments and wasn't sure about the development state of the studio.

However:
While programming I read through the function descriptions I used. And there is

Code: Select all

/**
 * @brief   Direct non-blocking read from a @p SerialDriver.
 * @note    This function bypasses the indirect access to the channel and
 *          reads directly from the input queue. This is faster but cannot
 *          be used to read from different channels implementations.
 *
 * @see     chnReadTimeout()
 *
 * @api
 */
#define sdAsynchronousRead(sdp, b, n)                                       \
  chIQReadTimeout(&(sdp)->iqueue, b, n, TIME_IMMEDIATE)

What I understand of non-blocking read as "It takes what is there, and if nothing is there, it returns 0". I came to this idea as this function lacks the parameter of timeout.

On the other hand I see

Code: Select all

/**
 * @brief   Direct blocking read from a @p SerialDriver with timeout
 *          specification.
 * @note    This function bypasses the indirect access to the channel and
 *          reads directly from the input queue. This is faster but cannot
 *          be used to read from different channels implementations.
 *
 * @see     chnReadTimeout()
 *
 * @api
 */
#define sdReadTimeout(sdp, b, n, t)                                         \
  chIQReadTimeout(&(sdp)->iqueue, b, n, t)


What is clearly stated to block until the number of characters requested is received or the timeout has hit.

So good to know that the non blocking read can block...

So my second trial will be to sample each UART by 10ms into its own buffer by a separate thread....
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dual-UART-USB Monitor problem

Post by Giovanni »

My fault, you are correct, it is the asynchronous version...

Giovanni
Astralix
Posts: 5
Joined: Tue Sep 16, 2014 4:25 pm

Re: Dual-UART-USB Monitor problem

Post by Astralix »

I modified the code to use a single thread per UART. And I use a blocking read per thread with a timeout of 10ms.
https://github.com/Astralix/chibios-dua ... e/2threads
This seems to work, as long as there are not too much errors on the UART lines. If so, the whole things crashes pretty fast. I guess there is some work to do for the error handling.

I tried to pull out the few specific things per UART and put them into a struct, then call the creation of the thread two times, handing over the working struct as the arg pointer:
uart2tp = chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, &thdev_uart2);
uart3tp = chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, &thdev_uart3);
But this crashes almost immediately after start.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dual-UART-USB Monitor problem

Post by Giovanni »

You are using the same working area for two threads :)

Giovanni
Astralix
Posts: 5
Joined: Tue Sep 16, 2014 4:25 pm

Re: Dual-UART-USB Monitor problem

Post by Astralix »

Ah!

Ok, I thought the working area is reserved each time a thread is installed. A few years ago I ported NutOS to STM32 and there it is like
NutThreadCreate("t1", Thread1, 0, 512);
The threads memory is pulled from system heap ( in this case 512 bytes)

So I have to double the reservation of working memory
static WORKING_AREA(waThread2, 128 + 2* RX_BUF_SZ + 50);

Is there a more dynamic way of doing this in Chibios?

Back to the 2-thread version:
I thought I use Heap and reduce the static load of the memory. I tried back and forth but the system still crashes. I am currently not aware if it is the RX (UART) part or the USB part. Some data at 250000k is fast enough to kill the beast. So I need to install the complete Studio I guess.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Dual-UART-USB Monitor problem

Post by Giovanni »

Sure, chThdCreateFromHeap().

However, usually dynamic allocation is not recommended in embedded systems.

Giovanni
Astralix
Posts: 5
Joined: Tue Sep 16, 2014 4:25 pm

Re: Dual-UART-USB Monitor problem

Post by Astralix »

Giovanni wrote:Sure, chThdCreateFromHeap().
However, usually dynamic allocation is not recommended in embedded systems.
Giovanni


Sorry, but that isn't correct by default. It really depends on every use-case and dynamic memory allocation can enable you to do things with a tiny embedded controller where others use RasPi or even bigger things.
But it takes much more thinking and planning, so it is not a beginners thing.

Astralix
Post Reply