diff --git a/CMakeLists.txt b/CMakeLists.txt index 53273bb8481f7b3ac5c2385fd4505fd29a0f90fe..45d913d806bd9ad7d4bba4b9c43f4f020d4927c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,8 @@ sbs_target(test-triad-parafoil stm32f429zi_parafoil) #-----------------------------------------------------------------------------# # Tests - Drivers # #-----------------------------------------------------------------------------# +add_executable(test-can-protocol src/tests/drivers/canbus/test-can-protocol.cpp) +sbs_target(est-can-protocol stm32f429zi_stm32f4discovery) add_executable(test-canbus-loopback src/tests/drivers/canbus/test-canbus-loopback.cpp) sbs_target(test-canbus-loopback stm32f429zi_stm32f4discovery) diff --git a/src/shared/drivers/canbus/CanProtocol.h b/src/shared/drivers/canbus/CanProtocol.h index 1c69acf5cc3adfc006ef375b3da96e93ff2575dc..cf78a0c341fd185d846b8fc077c48e8d1497552d 100644 --- a/src/shared/drivers/canbus/CanProtocol.h +++ b/src/shared/drivers/canbus/CanProtocol.h @@ -23,6 +23,7 @@ #pragma once #include <ActiveObject.h> +#include <utils/Debug.h> #include <utils/collections/IRQCircularBuffer.h> #include "Canbus.h" @@ -70,22 +71,42 @@ struct CanData class CanProtocol : public ActiveObject { private: + miosix::FastMutex + mutex; // todo add mutex and create get data in can protocol CanbusDriver* can; // the physical can - IRQCircularBuffer<CanData, NPACKET>* + IRQCircularBuffer<CanData, NPACKET> buffer; // the buffer used to send data from CanProtocol to CanHandler public: /** * @brief Construct a new CanProtocol object * @param can CanbusDriver pointer. - * @param The circular buffer */ - CanProtocol(CanbusDriver* can, IRQCircularBuffer<CanData, NPACKET>* buffer) + CanProtocol(CanbusDriver* can) { this->can = can; } + + CanData + getPacket() // return the packet, if buffer is empty return an empty packet + { + CanData temp; + mutex.lock(); + if (!buffer.isEmpty()) + { + temp = buffer.pop(); + } + mutex.unlock(); + + return temp; + } + + bool isEmpty() { - this->can = can; - this->buffer = buffer; + mutex.lock(); + return buffer.isEmpty(); + mutex.unlock(); } + void waitEmpty() { buffer.waitUntilNotEmpty(); } + /** * @brief Takes a canData, it splits it into single canpacket with the * correct sequential id @@ -95,19 +116,35 @@ public: void sendCan(CanData toSend) //@requires toSen to not be empty { CanPacket packet; - packet.ext = true; - packet.length = toSend.len; - packet.id = (toSend.canId << 7) | idMask.firstPacket | - (toSend.len & idMask.leftToSend); - packet.data[0] = toSend.payload[0]; + uint32_t tempLen = toSend.len - 1; + uint32_t tempId = toSend.canId; + packet.ext = true; + packet.id = + (tempId << 7) | idMask.firstPacket | (tempLen & idMask.leftToSend); + packet.length = (toSend.payload[0] + 8) / + 8; // simple formula for upper approximation + for (int k = 0; k < packet.length; k++) + { + packet.data[k] = toSend.payload[0] >> (8 * k); + } + tempLen--; + can->send(packet); - uint8_t tempLen = toSend.len - 1; + TRACE("tosend len %d\n", toSend.len); + for (int i = 1; i < toSend.len; i++) { - packet.id = - packet.id | !idMask.firstPacket | (tempLen & idMask.leftToSend); + tempId = toSend.canId; + packet.id = (tempId << 7) | !(idMask.firstPacket) | + (tempLen & idMask.leftToSend); + packet.length = (toSend.payload[i] + 8) / 8; + for (int k = 0; k < packet.length; k++) + { + packet.data[k] = toSend.payload[i] << (8 * k); + } + TRACE("packetlen %d\n, dato %d\n", packet.length, packet.data[0]); + can->send(packet); tempLen--; - packet.data[i] = toSend.payload[i]; } } @@ -130,45 +167,55 @@ protected: can->getRXBuffer().waitUntilNotEmpty(); if (!can->getRXBuffer().isEmpty()) { - packet = can->getRXBuffer().pop().packet; - sourceId = packet.id & idMask.source; + packet = can->getRXBuffer().pop().packet; + + sourceId = packet.id & idMask.source; if (data[sourceId].canId == 0 || (data[sourceId].canId & idMask.source) == sourceId) { - if (sourceId & idMask.firstPacket) // it is a first - // packet of a data; + if (packet.id & idMask.firstPacket) // it is a first + // packet of a data; { - data[sourceId].len = packet.id & idMask.leftToSend; + data[sourceId].len = + (packet.id & idMask.leftToSend) + 1; data[sourceId].canId = packet.id >> 7; // discard the sequence number - // data[i].len = packet.length; } - if ((data[sourceId].len - data[sourceId].nRec) == + TRACE("pakcet %d, nrec %d, left %lu\n", packet.data[0], + data[sourceId].nRec, (packet.id & idMask.leftToSend)); + if ((data[sourceId].len - (data[sourceId].nRec + 1)) == (packet.id & idMask.leftToSend)) { - uint64_t tempPayload; + + uint64_t tempPayload = 0; for (int f = 0; f < packet.length; f++) { - tempPayload = - tempPayload & (packet.data[f] << (56 - f * 8)); + uint64_t tempData = packet.data[f]; + tempPayload = tempPayload | (tempData << (f * 8)); } data[sourceId] .payload[data[sourceId].len - - (packet.id & idMask.leftToSend)] = + (packet.id & idMask.leftToSend) - 1] = tempPayload; data[sourceId].nRec++; } + if (data[sourceId].nRec == data[sourceId].len) { - buffer->put(data[sourceId]); + mutex.lock(); + buffer.put(data[sourceId]); + // empties the struct + data[sourceId].canId = 0; + data[sourceId].nRec = 0; + data[sourceId].len = 0; + mutex.unlock(); } - break; } } } } }; } // namespace Canbus -} // namespace Boardcore \ No newline at end of file +} // namespace Boardcore diff --git a/src/tests/drivers/canbus/test-canprotocol.cpp b/src/tests/drivers/canbus/test-can-protocol.cpp similarity index 75% rename from src/tests/drivers/canbus/test-canprotocol.cpp rename to src/tests/drivers/canbus/test-can-protocol.cpp index 2ea486a4a473c2a463ca0c42eba396a1638e2ee7..e2126819497d35abdf939256d70a0e4bd8fb3caf 100644 --- a/src/tests/drivers/canbus/test-canprotocol.cpp +++ b/src/tests/drivers/canbus/test-can-protocol.cpp @@ -1,3 +1,5 @@ + + /* Copyright (c) 2022 Skyward Experimental Rocketry * Author: Federico Mandelli * @@ -21,7 +23,9 @@ */ #include <drivers/canbus/CanProtocol.h> -#include <utils/Debug.h> +#include <inttypes.h> + +#include <thread> #include "drivers/canbus/BusLoadEstimation.h" #include "drivers/canbus/Canbus.h" @@ -45,6 +49,18 @@ using CanRX = Gpio<GPIOA_BASE, 11>; using CanTX = Gpio<GPIOA_BASE, 12>; #endif +#define SLP 5000 + +void sendData(CanProtocol* protocol, CanData toSend) +{ + while (true) + { + TRACE("send\n"); + (*protocol).sendCan(toSend); + Thread::sleep(SLP); + } +} + int main() { @@ -68,45 +84,48 @@ int main() bt.baudRate = BAUD_RATE; bt.samplePoint = SAMPLE_POINT; - IRQCircularBuffer<CanData, NPACKET>* buffer; CanbusDriver* c = new CanbusDriver(CAN1, cfg, bt); - CanProtocol protocol(c, buffer); - + CanProtocol protocol(c); // Allow every message Mask32FilterBank f2(0, 0, 0, 0, 0, 0, 0); c->addFilter(f2); c->init(); - protocol.start(); - - const int slp = 500; CanData toSend; toSend.canId = 0x01; toSend.len = 3; toSend.payload[0] = 1; toSend.payload[1] = 2; toSend.payload[2] = 3; + std::thread second(sendData, &protocol, toSend); for (;;) { - protocol.sendCan(toSend); - (*buffer).waitUntilNotEmpty(); - CanData temp = (*buffer).IRQpop(); + TRACE("start \n"); + protocol.waitEmpty(); + CanData temp = protocol.getPacket(); if (temp.canId != toSend.canId || temp.len != toSend.len || temp.payload[0] != toSend.payload[0] || temp.payload[1] != toSend.payload[1] || temp.payload[2] != toSend.payload[2]) { TRACE("Error\n"); - TRACE("Expected id %d , received %d\n", toSend.canId, temp.canId); + TRACE("Expected id %lu, received %lu\n", toSend.canId, temp.canId); TRACE("Expected len %d , received %d\n", toSend.len, temp.len); - TRACE("Expected payload 0 %d , received %d\n", toSend.payload[0], - temp.payload[0]); - TRACE("Expected payload 1 %d , received %d\n", toSend.payload[1], - temp.payload[1]); - TRACE("Expected payload 2 %d , received %d\n", toSend.payload[2], - temp.payload[2]); + TRACE( + "Expected payload 0 %llu , received " + "%llu\n", + toSend.payload[0], temp.payload[0]); + TRACE("Expected payload 1 %llu, received %llu\n", + toSend.payload[1], temp.payload[1]); + TRACE( + "Expected payload 2 %llu, received " + "%llu\n", + toSend.payload[2], temp.payload[2]); + } + else + { + TRACE("OK :)\n"); } - Thread::sleep(slp); } }