Nico Bollen / LIN

Dependents:   MBED_LIN_RGB_Master_Example

Files at this revision

API Documentation at this revision

Comitter:
bollenn
Date:
Mon Jun 15 12:42:04 2020 +0000
Parent:
7:53b2cded83f3
Commit message:
Rework receive path

Changed in this revision

LinMaster.cpp Show annotated file Show diff for this revision Revisions of this file
LinMaster.h Show annotated file Show diff for this revision Revisions of this file
--- a/LinMaster.cpp	Mon Jun 08 11:59:35 2020 +0000
+++ b/LinMaster.cpp	Mon Jun 15 12:42:04 2020 +0000
@@ -27,17 +27,16 @@
 
 const uint8_t breakPeriodMessage = 40;                      /* number of timer overflows in the break field during normal LIN messages */
 const uint8_t breakPeriodAcfg = 74;                         /* number of timer overflows in the break field during autoconfig messages */
-    
-LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin), LinIntPin(InPin)
+
+LinMaster::LinMaster(PinName InPin, PinName OutPin) : LinOutPin(OutPin), LinInPin(InPin, PullUp)
 {
-    this->DriverState  = INIT;
-    this->LastError    = NoError;
+    this->DriverState = INIT;
+    this->LastError = NoError;
     
     this->LinOutPin.write(1);
-    
-    this->LinInPin.mode(PullUp);
-    
-    this->LinIntPin.disable_irq();
+
+    this->LinInPin.disable_irq();
+    this->LinInPin.fall(NULL);
     
     this->DriverState = IDLE;
     
@@ -46,65 +45,66 @@
 
 LinMaster::~LinMaster()
 {
-    this->LinIntPin.disable_irq();
-    this->MyTicker.detach(); 
-    this->MyTimer.stop();
+    this->LinInPin.disable_irq();
+    this->LinInPin.fall(NULL);
+    this->HalfbitTicker.detach(); 
+    this->TimeoutTicker.detach();
 }
 
 bool LinMaster::init(void)
 {
     this->LinOutPin.write(1);
-    
-    this->LinInPin.mode(PullUp);
 
-    this->LinIntPin.disable_irq();
-    
+    this->LinInPin.enable_irq();
+    this->LinInPin.fall(NULL);
+
     this->DriverState = IDLE;
-    
+
     return ( true );
 }
 
 bool LinMaster::baudrate(uint16_t uBaud)
 {
     bool blReturn = false;
-    
+
     if ((uBaud > 0) && (uBaud <= 20000))
     {
-        this->u16HalfBitPeriod = 1000000/(2*uBaud);
+        this->u16HalfBitPeriod = std::chrono::microseconds(1000000 / ( 2 * uBaud));
         blReturn = true;
     }
-    
+
     return ( blReturn );
 }
 
 uint16_t LinMaster::baudrate(void)
 {
-    return ( 1000000 / (2 * this->u16HalfBitPeriod) );
+    return ( 1000000 / (2 * this->u16HalfBitPeriod.count()) );
 }
 
 bool LinMaster::send_frame(Frame_t * ptrFrame)
 {
     bool blReturn = false;
-    
+
     if ( (this->DriverState == IDLE) && (this->LinInPin.read() == 1) )
     {
         /* Clear and initialize all registers */
         memset(this->RXbuf, 0, 11);
-        
-        /* Disable half bit interrupt */
-        this->MyTicker.detach();
-        
-        this->LinIntPin.disable_irq();
-        
+
+        /* Disable ticker interrupt */
+        this->HalfbitTicker.detach();
+        this->TimeoutTicker.detach();
+
+        this->LinInPin.fall(NULL);
+
         this->LinOutPin.write(1);
-        
+
         this->DriverState = TRANSMIT;                       /* State of the LIN bus is transceiving a frame */
         this->LastError = NoError;
         this->FrameStatus = FStart;
         this->ByteStatus = BStart;
         this->RXbufIndex = 0;                               /* Reset index in the receiver buffer */
         this->TXbufIndex = 0;                               /* Reset index in the transmit buffer */
-    
+
         /* Set the correct brake-length */
         if (ptrFrame->Brake == AutoConfig)
         {
@@ -114,19 +114,19 @@
         {
             this->breakLength = breakPeriodMessage;
         }
-    
+
         this->FrameLength = 1 + 1 + ptrFrame->DataLen + 1;  /* Frame length = Sync + Frame ID + Data Len + CRC */
         this->linMessageType = ptrFrame->FrameType;
-    
+
         /* Create the correct frame buffer */
         this->TXbuf[0] = 0x55;                              /* Sync field */
         this->TXbuf[1] = this->parity(ptrFrame->FrameID);   /* Frame ID */
-    
+
         if (this->linMessageType == M2S)
         {
             uint16_t u16Crc;
             uint8_t i;
-            
+
             if (ptrFrame->CrcType == Enhanced)
             {
                 u16Crc = TXbuf[1];
@@ -135,7 +135,7 @@
             {
                 u16Crc = 0;
             }
-    
+
             for (i = 0; i < ptrFrame->DataLen; i++)
             {
                 this->TXbuf[i + 2] = ptrFrame->Data[i];     /* Data */
@@ -150,13 +150,14 @@
         else
         {
             /* S2M message */
-            this->RXtimeout = ((ptrFrame->DataLen + 1) * 14) * 2;   /* Calculate RX timeout in half bit-times */
-            this->RXtimeoutSubCTR = 0;
+
+            /* Calculate RX timeout */
+            this->FrameTimeout = std::chrono::microseconds(((ptrFrame->DataLen + 1) * 14) * 2 * this->u16HalfBitPeriod);
         }
-    
+
         /* Configure and start the half bit timer */
-        this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
-        
+        this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
+
         blReturn = true;
     }
     
@@ -205,6 +206,8 @@
 
 void LinMaster::TickEventHndl(void)
 {
+    int PinLevel = this->LinInPin.read();
+
     if (this->FrameStatus < Break_OK)
     {
         /* Do break field transmission */
@@ -235,11 +238,12 @@
         {
             /* No data needs to be transmitted */
             
-            /* Disable half bit interrupt */
-            this->MyTicker.detach();
+            /* Disable ticker interrupt */
+            this->HalfbitTicker.detach();
+            this->TimeoutTicker.detach();
             
             /* Disable LIN bus level interrupt */
-            this->LinIntPin.disable_irq();
+            this->LinInPin.fall(NULL);
         }
         else
         {
@@ -253,27 +257,11 @@
                     this->ByteStatus = static_cast<ByteStatus_t>(static_cast<int>(this->ByteStatus)+1);
                 }
 
-                if (this->RXtimeout > 0)
-                {
-                    this->RXtimeout--;
-                }
-                else
-                {
-                    this->DriverState = IDLE;
-                    this->LastError = NoSlaveResp;
-                    
-                    /* Disable half bit interrupt */
-                    this->MyTicker.detach();
-                    
-                    /* Disable LIN bus level interrupt */
-                    this->LinIntPin.disable_irq();
-                }
-
                 /* S2M message data receiving */
                 switch (this->ByteStatus)
                 {
                 case StartbitSample:
-                    if (LinInPin.read() == 0)
+                    if (PinLevel == 0)
                     {
                         /* OK */
                     }
@@ -294,43 +282,44 @@
                 case Databit7Sample:
                     /* Mid of single bit time, do sampling */
                     this->RXbuf[RXbufIndex] >>= 1;
-                    this->RXbuf[RXbufIndex] |= (LinInPin.read() << 7);
+                    this->RXbuf[RXbufIndex] |= (PinLevel << 7);
                     break;
 
                 case StopbitSample:
                     /* End of stop bit, stop Timer IRQ */
+
+                    /* Enable LIN bus level interrupt */
+                    this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
+
+                    /* Disable half bit interrupt */
+                    this->HalfbitTicker.detach();
+
+                    /* Check the current bus level */
+                    if (PinLevel == 0)
+                    {
+                        this->LastError = FramingErr;       /* stop bit not valid => framing error */
+                    }
+
                     this->RXbufIndex++;
                     this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
                     this->ByteStatus = BStart;
 
-                    /* Check the current bus level */
-                    if (this->LinInPin.read() == 0)
-                    {
-                        this->LastError = FramingErr;       /* stop bit not valid => framing error */
-                    }
-
                     if ((this->RXbufIndex >= this->FrameLength) ||
                         (this->LastError != NoError))
                     {
                         /* All requested data bytes are received or an error occurred */
                         this->DriverState = IDLE;
                         
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
+
+                        /* Disable timeout ticker */
+                        this->TimeoutTicker.detach();
                     }
                     else
                     {
                         /* Wait for a new data byte */
-                        this->MyTimer.start();
-                        
-                        /* Disable LIN bus level interrupt */
-                        this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
-                        this->LinIntPin.enable_irq();
                     }
-
                     break;
                     
                 case Databit0Edge:
@@ -398,7 +387,7 @@
                 case Databit7Sample:
                     /* Odd overflow, mid of bit time ==> sample the bus for RX */
                     this->RXbuf[this->RXbufIndex] >>= 1;
-                    this->RXbuf[this->RXbufIndex] |= ((LinInPin.read() << 7) & 0x80);
+                    this->RXbuf[this->RXbufIndex] |= ((PinLevel << 7) & 0x80);
                     break;
 
                 case StopbitEdge:
@@ -408,54 +397,56 @@
 
                 case StopbitSample:
                     /* Stop bit : mid / level check */
-                    if (this->LinInPin.read() == 0)
+                    if (PinLevel == 0)
                     {
                         /* Stop bit not valid => framing error */
                         this->LastError = FramingErr;
                         this->DriverState = IDLE;
-                        
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
+
+                        /* Disable ticker interrupt */
+                        this->HalfbitTicker.detach();
+                        this->TimeoutTicker.detach();
+
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
                     }
 
+                    this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
+                    this->TXbufIndex++;
+                    this->RXbufIndex++;
+
+                    if ((this->linMessageType == S2M) && (this->FrameStatus == ID_OK))
+                    {
+                        /* Stop bit of header is sent, now start receiving data bytes */
+
+                        /* Enable LIN bus level interrupt */
+                        this->LinInPin.fall(callback(this, &LinMaster::PinEventHndl));
+
+                        /* Disable half bit interrupt */
+                        this->HalfbitTicker.detach();
+
+                        /* Enable frame timeout interrupt */
+                        this->TimeoutTicker.attach(callback(this, &LinMaster::RXtimeoutEventHndl), this->FrameTimeout);
+                    }
                     break;
 
                 case BDone:
                     /* Stop bit : finished */
                     this->ByteStatus = BStart;
-                    this->FrameStatus = static_cast<FrameStatus_t>(static_cast<int>(this->FrameStatus)+1);
-                    this->TXbufIndex++;
-                    this->RXbufIndex++;
 
-                    if (this->linMessageType == S2M)
-                    {
-                        /* S2M frame */
-                        if (this->FrameStatus == ID_OK)
-                        {
-                            /* Stop bit of header is sent, now start receiving data bytes */
-                            this->MyTimer.start();
-                            
-                            /* Enable LIN bus level interrupt */
-                            this->LinIntPin.fall(this, &LinMaster::PinEventHndl);
-                            this->LinIntPin.enable_irq();
-                        }
-                    }
-                    else if (this->TXbufIndex >= this->FrameLength)
+                    if (this->TXbufIndex >= this->FrameLength)
                     {
                         /* M2S frame, Last byte is sent */
                         this->LastError = NoError;
                         this->DriverState = IDLE;
-                        
-                        /* Disable half bit interrupt */
-                        this->MyTicker.detach();
-                        
+
                         /* Disable LIN bus level interrupt */
-                        this->LinIntPin.disable_irq();
+                        this->LinInPin.fall(NULL);
+
+                        /* Disable ticker interrupts */
+                        this->TimeoutTicker.detach();
+                        this->HalfbitTicker.detach();
                     }
-
                     break;
 
                 default:
@@ -466,6 +457,19 @@
     }
 }
 
+void LinMaster::RXtimeoutEventHndl(void)
+{
+    /* Disable LIN bus level interrupt */
+    this->LinInPin.fall(NULL);
+
+    /* Disable half bit interrupt */
+    this->HalfbitTicker.detach();
+    this->TimeoutTicker.detach();
+
+    this->DriverState = IDLE;
+    this->LastError = NoSlaveResp;
+}
+
 void LinMaster::PinEventHndl(void)
 {
     switch (this->DriverState)
@@ -473,29 +477,16 @@
     case TRANSMIT:
     case RECEIVE:
     {
-        this->ByteStatus = StartbitEdge;                    /* Set status of the received byte */
-        this->RXtimeoutSubCTR += this->MyTimer.read_us();
-        this->MyTimer.stop();
-        
+        this->ByteStatus = StartbitSample;                  /* Set status of the received byte */
+
         /* Reset ticker */
-        this->MyTicker.detach();
-        this->MyTicker.attach_us(this, &LinMaster::TickEventHndl, this->u16HalfBitPeriod);
-        
+        this->HalfbitTicker.attach(callback(this, &LinMaster::TickEventHndl), this->u16HalfBitPeriod);
+
         /* Disable LIN bus level interrupt */
-        this->LinIntPin.disable_irq();
-
-        if (this->RXtimeoutSubCTR > this->u16HalfBitPeriod)
-        {
-            this->RXtimeoutSubCTR -= this->u16HalfBitPeriod;
-            if (this->RXtimeout > 0)
-            {
-                this->RXtimeout--;
-            }
-        }
-
+        this->LinInPin.fall(NULL);
         break;
     }
-    
+
     case IDLE:
     case DOMINANT:
     case TXWAKEUP:
--- a/LinMaster.h	Mon Jun 08 11:59:35 2020 +0000
+++ b/LinMaster.h	Mon Jun 15 12:42:04 2020 +0000
@@ -22,11 +22,11 @@
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
- 
-#include "mbed.h"
 
 #ifndef MBED_LIN_MASTER_H
 #define MBED_LIN_MASTER_H
+ 
+#include "mbed.h"
 
 /**  A master device LIN communication library for mbed
  *
@@ -88,7 +88,7 @@
      *   The current configured LIN baudrate
      */
     uint16_t baudrate(void);
-    
+
     /** Bus status */
     enum DriverStatus_t {
         INIT,           /**< initializing */
@@ -128,19 +128,19 @@
         S2M,
         M2S
     };
-    
+
     /** CRC Type */
     enum CrcType_t {
         Classic,
         Enhanced
     };
-    
+
     /** Brake Type */
     enum BrakeType_t {
         Normal,
         AutoConfig
     };
-    
+
     /** Frame */
     struct Frame_t {
         FrameType_t FrameType;
@@ -150,7 +150,7 @@
         uint8_t FrameID;
         uint8_t Data[8];
     };
-    
+
     /** Send a frame on the LIN bus
      *
      * @param ptrFrame pointer to the frame to transmit
@@ -159,7 +159,7 @@
      *   false on fail
      */
     bool send_frame(Frame_t * ptrFrame);
-    
+
     /** Receive a frame on the LIN bus
      *
      * @param ptrFrame pointer to the frame to receive
@@ -168,9 +168,11 @@
      *   false on fail
      */
     bool get_rx_data(Frame_t & ptrFrame);
-    
+
     void TickEventHndl(void);
-    
+
+    void RXtimeoutEventHndl(void);
+
     void PinEventHndl(void);
 
 private:
@@ -189,7 +191,7 @@
         Data7,
         CRC
     };
-    
+
     enum ByteStatus_t {
         BStart,
         StartbitEdge,               /* Begin of startbit received */
@@ -223,21 +225,19 @@
 
     uint8_t  breakLength;
     uint8_t  FrameLength;
-    
+
     uint8_t  TXbuf[11];
     uint8_t  TXbufIndex;
     uint8_t  RXbuf[11];
     uint8_t  RXbufIndex;
-    uint8_t  RXtimeout;
-    uint16_t RXtimeoutSubCTR;
-    uint16_t u16HalfBitPeriod;
+    std::chrono::microseconds u16HalfBitPeriod;
 
-    DigitalOut  LinOutPin;
-    DigitalIn   LinInPin;
-    InterruptIn LinIntPin;
-    Ticker   MyTicker;
-    Timer    MyTimer;
-    
+    DigitalOut LinOutPin;
+    InterruptIn LinInPin;
+    std::chrono::microseconds FrameTimeout;
+    Ticker HalfbitTicker;
+    Ticker TimeoutTicker;
+
     uint8_t parity(uint8_t u8BYTE);
 
 };