fix Rx edge sensitivity to recover from framing error / BREAK#526
fix Rx edge sensitivity to recover from framing error / BREAK#526gicking wants to merge 1 commit intoarduino:mainfrom
Conversation
maidnl
left a comment
There was a problem hiding this comment.
This is a "quick and dirty" way to fix the problem.
It misses something: the fact that the pin Irq is set to CHANGE allows the timer to be restarted at every front of the bit reception assuring the greatest possible accuracy with timing.
Besides the PR is issued for LIN SYNC BREAK field. I must say I did not check the LIN library implementation for lack time, so forgive me if a am wrong. I suppose that if you are using Serial Software to handle LIN communication you are treating the SYNC BREAK field as something special (a received 0x00 with a missing stop bit, I suppose). But this is not a "true" SYNC. It is again something quick and dirty (again sorry if this is not the case).
In my opinion it would be better to have a more comprehensive PR that takes care of the particularity of the SYNC BREAK field (line kept low for more than 13 bytes): a function that "suspends" Serial Software and checks for a true SYNC and then restarts the Serial Software when a SYNC BREAK field is received. This would be beneficial for 2 reasons: it will not reduce the sync capabilities of this library and it will truly check for a SYNC LIN frame, compliant with LIN specification.
Saying that this PR should not harm Serial Software, but only reduce its own re-sync capacities.
|
You are correct in that I only tried to solve a problem, not re-write the library. But the title may be misleading (because I am working on LIN): IMHO the issue occurs whenever the rising edge of the stop-bit is missed, e.g. due to a framing error. In this case the (too late) rising edge of the stop-bit is mistaken as the falling edge of the next start bit. This leads to a loss of sync and wrong data.
At least this hypothesis explains what I see. Without knowing the details, I guess the correct way is to set the edge sensitivity according to the state. Specifically, at the end of a byte, i.e., also after timeout/FE, set sensitivity to FALLING. After reception of the initial falling edge, change to CHANGE. But, as said, I am the wrong person for that, as I don't know about DMA or it's use in this lib.
As for LIN spec compliance: due to the limitations of the different controllers, implementations and/or Arduino framework, I cannot hope to be fully spec compliant (and don't claim to be). Where possible I synchronize on 0x00 w/FE, followed by 0x55. Where that is not available, I use inter-frame pause (like Modbus RTU), followed by 0x00+0x55. As said, not LIN spec compliant but it works.
The only board/core that gives me headache is the Arduino Uno R4 Minima/Renesas which shows all kinds of weird issues:
- SoftwareSerial loses sync systematically for LIN slaves (this issue)
- UART does not allow to generate a BREAK for LIN master (see #524)
Very frustrating!
|
|
After thinking about this a bit more, I no longer understand why my PR works - but I have a hunch... Maybe you can enlighten me. If I understand the concept correctly(?), SoftwareSerial reception works like this
If this understanding is correct(?), there is no way that only FALLING (or RISING) edge can work. Because if e.g. only falling edges are stored, the SW cannot distinguish between bit patterns 10110 and 10010. But since my empirical tests did work (see here), I suspect that that only above step 1 is impacted by the edge sensitivity which I changed, and that the DMA triggers for step 2 have their own sensitivity (which I did not change). And step 3 is anyway triggered by the time overflow. Is this understanding correct or is my thinking completely off...? For your feedback thanks a lot in advance! |
I maintain an Arduino library for LIN master emulation. A LIN frame starts with a BREAK signal (>13b low).
With the original SoftwareSerial implementation I was unable to receive anything after BREAK. On deeper analysis I found that the selected Rx-IRQ edge sensitivity (CHANGING) interprets the rising edge of the BREAK as the start bit for the next byte (see screenshot), which leads to loss of sync.
However, when I change the Rx edge sensitivity to only falling (or rising for inverted logic), the issue disappears and I can receive the complete frame without hassle :-)
To verify this fix I checked the Rx reception after a BREAK (aka FE) using the below sketch. Here are the logs for original (all fail) and fix (all ok)