0
\$\begingroup\$

I'm trying to read and write data to a LIN Bus, which is a single wire bus. As such, only one "module" (my PIC is a module in a network) is allowed to talk at a time. I'm using an MCP2004 LIN transceiver, and my device is a slave on the network. I'm unsure what hardware the master and other slaves utilize.

The problem I'm running into is that sometimes, a byte is pushed onto the Bus at the same time I'm pushing one out, which results in a frame error.

In my firmware, I have an interrupt service routine for RX from that Bus, and it has the highest ISR priority set (7). The problem is that as the program continues to execute, it's not always possible for me to tell if there's data thats been received.

Right now, I check my RX buffer size prior to transmission, but sometimes the byte is received after that conditional, but right before I actually write data to the bus. I'm also checking UxSTA, but I doubt that helps, since if there's data on the hardware buffer, the program would be in the ISR, and not my main code.

It may be worthy to note that I'm not transmitting in an ISR.

What's the best way for me to handle this contention? Is it advisable to keep the program in the ISR for the entirety of the data reception? The protocol does contain a message length byte and a checksum.

\$\endgroup\$
  • 1
    \$\begingroup\$ an ISR should always do as little processing as possible so that interrupts do not get missed \$\endgroup\$ – jsotola Jul 20 '18 at 16:43
  • 1
    \$\begingroup\$ a byte is pushed onto the Bus at the same time I'm pushing one out .... according to a quick web search, this should not be happening ..... is your device a master or slave? \$\endgroup\$ – jsotola Jul 20 '18 at 16:57
  • \$\begingroup\$ @jsotola - My device is a slave. My PIC is simply using a UART module for communication, so I think the LIN transceiver (MCP2004) is where the data is being corrupted. \$\endgroup\$ – t3ddftw Jul 20 '18 at 17:00
  • 1
    \$\begingroup\$ it is unclear if the MCP2004 is part of the master or the slave ... maybe add more detail to your question ...... anyway, maybe the collision is happening because the master is not receiving your response or the master's program is messed up \$\endgroup\$ – jsotola Jul 20 '18 at 17:09
  • 1
    \$\begingroup\$ What's the best way for me to handle this contention? ..... there is nothing that you can do as far as continuing the transmit .... all you have to do, is to remember the data that was not sent .... the master is in charge .... if the master requires data or an ack from the slave, then it should ask for it again \$\endgroup\$ – jsotola Jul 20 '18 at 17:21
2
\$\begingroup\$

It sounds like the real solution is at a higher level of protocol. At a higher level, you should know when it's OK to send and when it's not.

I'm not familiar with LIN in particular, but there is probably a means of addressing this issue already defined as part of LIN. One possibility is that nodes send when they feel like, and the resulting collisions are detected and dealt with in a orderly manner. This is how CAN works, for example. Or, there is higher level logic to guarantee only one node at a time is supposed to transmit. Most RS-485 bus implementations work that way, for example. The Dallas one-wire bus works that way too.

Implement whatever mechanism that has already been decided upon.

\$\endgroup\$
  • \$\begingroup\$ Thanks! Unfortunately, the LIN to RS-232 transceiver doesn't expose the protocol to me, nor does it support 4 wire UART. \$\endgroup\$ – t3ddftw Jul 20 '18 at 17:08
0
\$\begingroup\$

What causes conflicts on the LIN bus?

The LIN protocol is designed so that most of the time there will be no conflicts. The master task polls slave tasks individually, the slaves are only allowed to transmit immediately in response to the master polling them.

There are a few reasons why a conflict might occur:

  • You are transmitting when you aren't supposed to
  • Another slave is transmitting when it isn't supposed to
  • The network has been poorly defined, so that multiple slaves are configured to respond to the same polling request
  • You are transmitting an event-driven frame

The first 3 reasons are major problems that need to be solved in the bus design. The last one is intentional: you're supposed to get conflicts on event-driven frames, that's how they work and the master will sort it out.


How do I detect conflicts on the LIN bus?

The LIN transceiver (and surrounding circuitry) serves a few purposes. The main one we care about is that it converts the 2-wire UART signal from your processor into a 1-wire LIN signal. The transceiver is all passive circuitry, it is continuously sending and continuously receiving. This means that everything byte you send you will also receive.

The only time this changes is if someone else is transmitting at the same time as you. If this happens, the transceiver will AND your transmissions together and you will receive the result. This will be a different byte than the one you transmitted.

Whenever you transmit a byte, you need to check that you receive the exact same byte back again. If you do not, there is another node transmitting at the same time as you.


What do I do when I detect a conflict on the LIN bus?

As soon as you detect a conflict stop transmitting. The master will detect the aborted transmission and act accordingly.

If this is happening regularly, and it is not an event-driven frame, you need to examine the entire bus:

  • Is one of the nodes acting out of spec and communicating when it shouldn't?

    You need to fix or replace this node.

  • Are two nodes configured to respond to the same header?

    You need to reconfigure one of the nodes to use a different header

  • Are you using multiple instances of the same slave node?

    You need to think about using a dynamic addressing system, like Slave Node Position Detection (SNPD).

\$\endgroup\$
0
\$\begingroup\$

With the exception of event frames (which you will know about if you are using them) there are no collisions possible on the LIN bus. There can only be one master, and all transmissions from a slave to that master are initialised by that same master.

Your code should not be transmitting until it has received an appropriate message header from the master (BREAK + SYNC + PID). Once it has received this, your code should know exactly how many bytes to send back (this is agreed when the bus is designed), and the master will allow your device 140% of the minimum transmission time in which to send this before an error is detected (it will guarantee the bus stays idle for this time).

There is only one other situation where something like a collision can occur, and that is if the master interrupts a transaction by sending a new BREAK sequence (13 bit times at dominant state). A properly designed slave should be able to recognise a BREAK sequence at any time, abandon the current transaction, and receive the new header. In practice it is normally enough to detect a read back error and stop transmitting when this occurs.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.