diff --git a/src/shared/drivers/canbus/CanProtocol.cpp b/src/shared/drivers/canbus/CanProtocol.cpp index 5f4fb440179ef5de65c8eaca061790985aa9d410..a1c8aade82ccd9ee2b246f69a9f21e7cdd668e18 100644 --- a/src/shared/drivers/canbus/CanProtocol.cpp +++ b/src/shared/drivers/canbus/CanProtocol.cpp @@ -30,51 +30,55 @@ namespace Canbus // For each board contains the packet that we are re-assembling CanData data[N_BOARDS]; -CanProtocol::CanProtocol(CanbusDriver* can) { this->can = can; } - -CanProtocol::~CanProtocol() { (*can).~CanbusDriver(); } - -CanData CanProtocol::getPacket() +CanProtocol::CanProtocol(CanbusDriver* can, MsgHandler callback) { - if (!buffer.isEmpty()) - return buffer.pop(); - else - return {}; + this->can = can; + this->callback = callback; } -bool CanProtocol::isBufferEmpty() { return buffer.isEmpty(); } +CanProtocol::~CanProtocol() { delete can; } -void CanProtocol::waitBufferNotEmpty() { buffer.waitUntilNotEmpty(); } +void CanProtocol::send(CanData toSend) { TXbuffer.put(toSend); } -void CanProtocol::sendData(CanData dataToSend) +void CanProtocol::sendData() { - CanPacket packet = {}; - uint8_t tempLen = dataToSend.length - 1; - uint32_t tempId = dataToSend.canId; - - // Send the first packet - packet.ext = true; - // create the id for the first packet - packet.id = (tempId << shiftSequentialInfo) | (63 - (tempLen & leftToSend)); - packet.length = byteForInt(dataToSend.payload[0]); - // Splits payload[0] in the right number of uint8_t - for (int k = 0; k < packet.length; k++) - packet.data[k] = dataToSend.payload[0] >> (8 * k); - can->send(packet); - tempLen--; - - for (int i = 1; i < dataToSend.length; i++) + + while (true) { - // create the id for the remaining packets - packet.id = (tempId << shiftSequentialInfo) | firstPacket | - (63 - (tempLen & leftToSend)); - packet.length = byteForInt(dataToSend.payload[i]); - // Splits payload[i] in the right number of uint8_t - for (int k = 0; k < packet.length; k++) - packet.data[k] = dataToSend.payload[i] >> (8 * k); - - can->send(packet); - tempLen--; + TXbuffer.waitUntilNotEmpty(); + if (!TXbuffer.IRQisEmpty()) + { + CanData dataToSend = TXbuffer.pop(); + CanPacket packet = {}; + uint8_t tempLen = dataToSend.length - 1; + uint32_t tempId = dataToSend.canId; + + // Send the first packet + packet.ext = true; + // create the id for the first packet + packet.id = + (tempId << shiftSequentialInfo) | (63 - (tempLen & leftToSend)); + packet.length = byteForInt(dataToSend.payload[0]); + // Splits payload[0] in the right number of uint8_t + for (int k = 0; k < packet.length; k++) + packet.data[k] = dataToSend.payload[0] >> (8 * k); + can->send(packet); + tempLen--; + + for (int i = 1; i < dataToSend.length; i++) + { + // create the id for the remaining packets + packet.id = (tempId << shiftSequentialInfo) | firstPacket | + (63 - (tempLen & leftToSend)); + packet.length = byteForInt(dataToSend.payload[i]); + // Splits payload[i] in the right number of uint8_t + for (int k = 0; k < packet.length; k++) + packet.data[k] = dataToSend.payload[i] >> (8 * k); + + can->send(packet); + tempLen--; + } + } } } @@ -94,11 +98,11 @@ uint8_t CanProtocol::byteForInt(uint64_t number) void CanProtocol::run() { + std::thread send(std::bind(&CanProtocol::sendData, this)); while (!shouldStop()) { // Wait for the next packet can->getRXBuffer().waitUntilNotEmpty(); - // If the buffer is not empty retrieve the packet if (!can->getRXBuffer().isEmpty()) { @@ -169,7 +173,7 @@ void CanProtocol::run() data[sourceId].nRec != 0) { // We put the element of data in buffer - buffer.put(data[sourceId]); + callback(data[sourceId]); // Empties the struct data[sourceId].canId = -1; diff --git a/src/shared/drivers/canbus/CanProtocol.h b/src/shared/drivers/canbus/CanProtocol.h index ebbc7e05ae0df39ca87c7c3235225eda3ebef22c..d2be1c2efe69dc3fba64068530dd3e6e8b4d5a5e 100644 --- a/src/shared/drivers/canbus/CanProtocol.h +++ b/src/shared/drivers/canbus/CanProtocol.h @@ -26,6 +26,8 @@ #include <utils/Debug.h> #include <utils/collections/IRQCircularBuffer.h> +#include <thread> + #include "Canbus.h" #define N_BOARDS 3 ///< Number of boards on the bus. @@ -115,14 +117,7 @@ struct CanData */ class CanProtocol : public ActiveObject { -private: - // The physical implementation of the CanBus - CanbusDriver* can; - - // The buffer used to store the completed CanData - IRQCircularBuffer<CanData, N_BOARDS> buffer; - - miosix::FastMutex mutex; + using MsgHandler = std::function<void(CanData data)>; public: /** @@ -130,22 +125,10 @@ public: * * @param can Pointer to a CanbusDriver object. */ - explicit CanProtocol(CanbusDriver* can); + explicit CanProtocol(CanbusDriver* can, MsgHandler callback); ~CanProtocol(); - /** - * @brief Returns the first packet in the buffer. - * - * If buffer is empty return an empty packet. - * @warning Should be called only after checking isEmpty() - */ - CanData getPacket(); - - bool isBufferEmpty(); - - void waitBufferNotEmpty(); - /** * @brief Sends a CanData object on the bus. * @@ -155,7 +138,7 @@ public: * * @param data Contains the id and the data of the packet to send. */ - void sendData(CanData dataToSend); + void send(CanData toSend); private: /** @@ -163,6 +146,8 @@ private: */ uint8_t byteForInt(uint64_t number); + void sendData(); + /** * @brief Keeps listening on the canbus for packets. * @@ -175,6 +160,16 @@ private: * CanHandler. */ void run() override; + + // The physical implementation of the CanBus + CanbusDriver* can; + + // The buffer used to store the CanData to send + IRQCircularBuffer<CanData, N_BOARDS> TXbuffer; + + miosix::FastMutex mutex; + + MsgHandler callback; }; } // namespace Canbus diff --git a/src/tests/drivers/canbus/test-can-protocol.cpp b/src/tests/drivers/canbus/test-can-protocol.cpp index 598adf32b4e4c9a459fc4c22d54e38235a2d9e06..04b1fae84d928f8b93fb18d67fbea7f78c3a15f6 100644 --- a/src/tests/drivers/canbus/test-can-protocol.cpp +++ b/src/tests/drivers/canbus/test-can-protocol.cpp @@ -24,6 +24,7 @@ #include <drivers/canbus/CanProtocol.h> +#include <functional> #include <thread> #include "drivers/canbus/BusLoadEstimation.h" @@ -46,23 +47,10 @@ using CanRX = Gpio<GPIOA_BASE, 11>; using CanTX = Gpio<GPIOA_BASE, 12>; #endif -#define SLP 5 +#define SLP 100 miosix::FastMutex mutex; CanData toSend1; CanData toSend2; -void sendData(CanProtocol* protocol, CanData* toSend) -{ - while (true) - { - - // TRACE("send id %d\n", toSend->canId); - { - miosix::Lock<miosix::FastMutex> l(mutex); - (*protocol).sendData(*toSend); - } - Thread::sleep(SLP); - } -} bool equal(CanData* first, CanData* second) { if ((*first).canId != (*second).canId || @@ -78,6 +66,36 @@ bool equal(CanData* first, CanData* second) return true; } +void print(CanData data) +{ + if ((!equal(&data, &toSend1) && !equal(&data, &toSend2))) + { + TRACE("Error\n"); + TRACE("Received id %lu\n", data.canId); + TRACE("length %d\n", data.length); + for (int i = 0; i < data.length; i++) + { + TRACE("Received payload %d: %llu,\n", i, data.payload[i]); + } + } + else + { + TRACE("OK :) id %lu\n", data.canId); + } +} +void sendData(CanProtocol* protocol, CanData* toSend) +{ + while (true) + { + + // TRACE("send id %d\n", toSend->canId); + { + miosix::Lock<miosix::FastMutex> l(mutex); + (*protocol).send(*toSend); + } + Thread::sleep(SLP); + } +} int main() { { @@ -99,7 +117,8 @@ int main() bt.baudRate = BAUD_RATE; bt.samplePoint = SAMPLE_POINT; CanbusDriver* c = new CanbusDriver(CAN1, cfg, bt); - CanProtocol protocol(c); + CanProtocol protocol(c, + &print); // std::bind(&print, std::placeholders::_1)); // Allow every message Mask32FilterBank f2(0, 0, 1, 1, 0, 0, 0); @@ -117,7 +136,7 @@ int main() toSend1.payload[5] = 3234; toSend1.payload[6] = 12; toSend1.payload[7] = 0; - std::thread firstSend(sendData, &protocol, &toSend1); + // std::thread firstSend(sendData, &protocol, &toSend1); Thread::sleep(10); toSend2.canId = 0x100; @@ -127,32 +146,15 @@ int main() toSend2.payload[2] = 0x123ff; toSend2.payload[3] = 1; std::thread secondSend(sendData, &protocol, &toSend2); + + /* code */ + TRACE("start \n"); - int error = 0; - for (int f = 0; f < 100000; f++) + while (true) { - protocol.waitBufferNotEmpty(); - CanData temp = protocol.getPacket(); + protocol.send(toSend1); + Thread::sleep(SLP); + // TRACE("received packet \n"); - if ((!equal(&temp, &toSend1) && !equal(&temp, &toSend2))) - { - error++; - TRACE("Error\n"); - TRACE("Received id %lu\n", temp.canId); - TRACE("length %d\n", temp.length); - for (int i = 0; i < temp.length; i++) - { - TRACE("Received payload %d: %llu,\n", i, temp.payload[i]); - } - } - else - { - TRACE("OK :) id %lu\n", temp.canId); - } - } - if (error != 0) - { - TRACE("Number of Error %d\n", error); } - free(c); }