Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MBED_LIN_RGB_Master_Example
Diff: LinMaster.cpp
- Revision:
- 8:63d341e53cce
- Parent:
- 5:b42737f5dabc
--- 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: