How to download a file through a RS485 link

Started by Aina 6 years ago13 replieslatest reply 6 years ago1682 views


I need to download a file on an STM32 through a half-duplex RS485 link. For the moment, it is using modbus (slave) to talk with a PC, and it is working fine.

As modbus is not really efficient to transfer big amont of data, I planned to stop modbus when I need to download a file, and use Ymodem instead.

But when I try to send simple ASCII characters to my hyperterminal, most of the time I do not get what I expected, and sometimes, for an obscure reason, it is working fine.

I compared the data I receive on my computer to the ones I send on my board, and there is no obvious link between them, like bit shift or LSB first/ MSB first inversion.

I also tried to send a simple file from my computer with Ymodem protocol, but my board was unable to recognize the starting sequence.

I do not understand where I am going wrong.

Any help? Thanks a lot in advance

[ - ]
Reply by bamosSeptember 20, 2018

Since you didn't state your exact MCU, here are some general suggestions:

  1. 1.  Figure out what's going on with the unexpected characters (if you can't send simple ASCII characters, there's absolutely no hope to put a protocol on top)
    1. double check your UART isn't configured for one of the "addressed modes", which effectively requires a 9th bit with rules around using it (not widely supported on the PC side)
      1. There's a fairly lengthy thread here about "9it RS485": https://www.embeddedrelated.com/showthread/comp.ar...
    2. if your modbus implementation requires the uart to decode a 9th bit to signal addressing, you'll want to modify the UART peripheral configuration before/after receiving the file
  2. If you haven't already, check out this example from ST which implements YMODEM over UART:
    1. https://www.st.com/en/embedded-software/stsw-stm32...
    2. NOTE:  Current versions of TeraTerm don't seem to implement YMODEM is a way that is compatible with this code, try using an older version like 4.79
      1. http://en.osdn.jp/projects/ttssh2/downloads/59442/teraterm-4.79.exe
[ - ]
Reply by AinaSeptember 20, 2018

luckily I am using an 8-bits modbus protocol :-) I am using the ST code your are mentionning to implement Ymodem on my board, and ExtraPutty to transfer the file. I am using a STM32F407

[ - ]
Reply by CustomSargeSeptember 20, 2018

If it ever works fine, the problem is going to be flow control and/or timing. I'd also try to get it to full duplex. But for big data block transfers, half duplex isn't a hinderance. Check both ends for handshaking of lines like RTS / CTS and DTR / DSR / CD. It can also be in the datastream (xon / xoff), but that pretty much requires full duplex.

Check Wikipedia on "serial communication flow control". Hope your protocol was written properly with flow control supported. If not (seen it) you May be able to add it, or you have to approximate it through block size and timing. A dual trace o'scope or a data line analyzer is nearly required to do this well. It can be done without, but a Lot of baby steps and guessing is involved.

[ - ]
Reply by AinaSeptember 20, 2018

Seems like there is no flow control on my board, as I have only 2 wires connected to my computer :-(

[ - ]
Reply by MichaelKellettSeptember 20, 2018

If possible connect a scope to your system so you can see what is going on. If it's half duplex you need to be sure that the tx/tx directions of the driver chips are being set correctly.


[ - ]
Reply by AinaSeptember 20, 2018

Thank you every one for your replies. 

I succeeded to make the ASCII sending from my board work every time :-) The problem was due to the fact that I short-circuited UART configuration while short-circuiting modbus, so I was not using the right baudrate.

Now I need to understand why my board is only receiving 0x80  when I try a file transfer... 

[ - ]
Reply by mr_banditSeptember 20, 2018

Silly question: If you can compile and load code onto your board, why are you trying to download a file? Why not just compile the info as needed and load it to your board?

[ - ]
Reply by AinaSeptember 20, 2018

Because during product's life, we will have to remotely update our firmware. So we need a bootloader 

[ - ]
Reply by AinaSeptember 20, 2018

Hello everyone,

Next step in my adventures ;-)

Now I manage to get the first Ymodem packet (the one with the name and size of the file). But when my computer send the second one, my board sees it corrupted (CRC error).

I looked at the packet arriving at the input of my board thanks to a serial sniffer. Data is OK. But when I look at the data received by my UART, I see that bytes 144 to 147 are systematically replaced by a repeated 16-bit pattern (e.g: 0x0C 0F 0C 0F). This pattern can change between two transmissions of the same file, but always takes place in bytes 144 to 147.

I also checked the pin giving the tx direction on my board with an oscilloscope. It is set to "receive" mode during the whole transmission.

Any idea of what is going wrong? Thanks a lot in advance

PS: I also switched from ExtraPuTTy to the TeraTerm version advised by bamos to send my file

[ - ]
Reply by AinaSeptember 20, 2018


I looked at the reception buffer I am filling in my UART Rx interrupt: data is OK in it. So the problem is happening when I am copying these data to another table in my application with the simpliest instruction:

for(i = 0; i < PACKET_SIZE; i++)


data[i] = Buffer[i];


I looked at assembly code generated by my compiler. I do not see what couldd go wrong, especially because these instructions are repeated many times, but only for this particular set of bytes, it is going wrong...

The only hypothesis that I can make is that there is a hardware bug in my microcontroller. What do you think about it?

[ - ]
Reply by strubiSeptember 20, 2018

This sounds like a software bug to me, there are no known STM32 UART flaws known to me, except that you could run into issues with modbus timing due to too high system latencies (avoided easily, when you have a hardware RS485 support).

When you copy a block in 'user space' (not inside the IRQ handler): Think of this: what happens, if an IRQ gets in between?

The best way to avoid this is:

- Design a proper FIFO queue (ring or ping-pong-buffer)

- Make sure all your FIFO head/tail variables are accessed atomically

Also: avoid copying as far as possible, push the data inside the IRQ handler where it's needed or use DMA mode.

This can all be done on the STM32 without IRQ disabling (bad practise), if I recall right.

[ - ]
Reply by AinaSeptember 20, 2018

Hi srtubi,

I removed all the modbus protocol from my code, and the problem is still there. The only way I found to remove it was to use a local table to copy data from my reception buffer instead of a pointer passed as a parameter of my user function. Then I copy data to my pointer as soon as all of them are received. 

I also looked at the assembly code of my copy, all loads/stores are done atomically, so there is no risk of data corruption if an interrupt happens during it.

[ - ]
Reply by strubiSeptember 20, 2018

Hi Aina,

hard to say what's going wrong when not seeing the exact code, but: your copy loop (which is outside the IRQ handler, right?) can be interrupted. So your data buffer might be overwritten from the IRQ handler while 'user space' is copying it. You could bracket it by DISABLE_IRQ()/ENABLE_IRQ() statements (substitute by your arch-specific IRQ macros), but that's not good practise, esp. when you rely on precise timer interrupts/timing.