Multiple frames (#8)

* Add fields to mmr header

* Reorder priority constants

* Add message priority

* Add header to message

* Fix compile error

* Set correct bits in header

* Refactor

* Create queue
This commit is contained in:
Stefano Calabretti
2022-01-25 18:12:33 +01:00
committed by GitHub
parent e7bb09478e
commit 174f5e8d76
6 changed files with 117 additions and 69 deletions
+1 -1
View File
@@ -78,7 +78,7 @@ typedef struct {
* Represents a CAN message * Represents a CAN message
*/ */
typedef struct { typedef struct {
CanId senderId; MmrCanHeader header;
void *store; void *store;
} MmrCanMessage; } MmrCanMessage;
+14 -2
View File
@@ -24,18 +24,30 @@ typedef enum {
} MmrCanMessageType; } MmrCanMessageType;
typedef enum {
MMR_CAN_MESSAGE_PRIORITY_LOW = B_(0010),
MMR_CAN_MESSAGE_PRIORITY_NORMAL = B_(0001),
MMR_CAN_MESSAGE_PRIORITY_HIGH = B_(0000),
} MmrCanMessagePriority;
/** /**
* @brief * @brief
* This struct encodes the values stored inside the * This struct encodes the values stored inside the
* extended id field of a CAN packet. * extended id field of a CAN packet.
*/ */
typedef struct { typedef struct {
uint32_t priority : 5; MmrCanMessagePriority priority : 3;
uint32_t senderId : 23; uint32_t dictionaryEntry : 10;
uint32_t senderId : 12;
MmrCanMessageType messageType : 4; MmrCanMessageType messageType : 4;
} MmrCanHeader; } MmrCanHeader;
uint32_t *MMR_CAN_HeaderToBits(MmrCanHeader *header);
MmrCanHeader *MMR_CAN_HeaderFromBits(uint32_t *bits);
bool MMR_CAN_IsMultiFrame(MmrCanHeader *header); bool MMR_CAN_IsMultiFrame(MmrCanHeader *header);
bool MMR_CAN_IsMultiFrameEnd(MmrCanHeader *header); bool MMR_CAN_IsMultiFrameEnd(MmrCanHeader *header);
+14
View File
@@ -0,0 +1,14 @@
#ifndef INC_MMR_CAN_QUEUE_H_
#define INC_MMR_CAN_QUEUE_H_
#include <stdint.h>
#include "mmr_can.h"
#define MMR_CAN_QUEUE_SIZE 10
typedef struct {
MmrCanMessage messages[MMR_CAN_QUEUE_SIZE];
size_t count;
} MmrCanQueue;
#endif /* INC_MMR_CAN_QUEUE_H_ */
+9
View File
@@ -1,6 +1,15 @@
#include "mmr_can_header.h" #include "mmr_can_header.h"
#include "mmr_can_util.h"
#include "mmr_can_optimize.h" #include "mmr_can_optimize.h"
uint32_t *MMR_CAN_HeaderToBits(MmrCanHeader *header) {
return (uint32_t*)header;
}
MmrCanHeader *MMR_CAN_HeaderFromBits(uint32_t *bits) {
return (MmrCanHeader*)bits;
}
bool MMR_CAN_IsMultiFrame(MmrCanHeader *header) { bool MMR_CAN_IsMultiFrame(MmrCanHeader *header) {
return header->messageType == MMR_CAN_MESSAGE_TYPE_MULTI_FRAME; return header->messageType == MMR_CAN_MESSAGE_TYPE_MULTI_FRAME;
+10 -8
View File
@@ -1,14 +1,11 @@
#include <stdbool.h> #include <stdbool.h>
#include "mmr_can.h" #include "mmr_can.h"
static HalStatus receiveOne(ReceptionParams *rp);
static HalStatus receiveAll(ReceptionParams *rp);
static bool headerIsMultiFrame(MmrCanHeader *header, CanId targetId);
typedef struct { typedef struct {
CanHandle *handle; CanHandle *handle;
uint8_t *result; uint8_t *result;
struct { struct {
CanRxHeader rx; CanRxHeader rx;
MmrCanHeader mmr; MmrCanHeader mmr;
@@ -18,6 +15,11 @@ typedef struct {
} ReceptionParams; } ReceptionParams;
static HalStatus receiveOne(ReceptionParams *rp);
static HalStatus receiveAll(ReceptionParams *rp);
static bool headerIsMultiFrame(MmrCanHeader *header, CanId targetId);
/** /**
* @brief * @brief
* Reads a CAN message and stores it inside the * Reads a CAN message and stores it inside the
@@ -29,7 +31,7 @@ typedef struct {
HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) { HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) {
ReceptionParams rp = { ReceptionParams rp = {
.handle = hcan, .handle = hcan,
.result = interpretAs(uint8_t*, result->store), .result = (uint8_t*)result->store,
.fifo = MMR_CAN_RX_FIFO, .fifo = MMR_CAN_RX_FIFO,
}; };
@@ -38,7 +40,7 @@ HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) {
return status; return status;
} }
result->senderId = rp.headers.mmr.senderId; result->header = rp.headers.mmr;
if (MMR_CAN_IsMultiFrame(&rp.headers.mmr)) { if (MMR_CAN_IsMultiFrame(&rp.headers.mmr)) {
status |= receiveAll(&rp); status |= receiveAll(&rp);
} }
@@ -63,9 +65,9 @@ static HalStatus receiveAll(ReceptionParams *rp) {
static HalStatus receiveOne(ReceptionParams *rp) { static HalStatus receiveOne(ReceptionParams *rp) {
HalStatus status = HalStatus status =
HAL_CAN_GetRxMessage(rp->hcan, rp->fifo, &(rp->headers.rx), rp->result); HAL_CAN_GetRxMessage(rp->handle, rp->fifo, &(rp->headers.rx), rp->result);
rp->headers.mmr = convertTo(MmrCanHeader, header->ExtId); rp->headers.mmr = convertTo(MmrCanHeader, rp->headers.rx.ExtId);
return status; return status;
} }
+69 -58
View File
@@ -3,57 +3,63 @@
#include "mmr_can_util.h" #include "mmr_can_util.h"
static HalStatus sendNormal(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet); typedef struct {
static HalStatus sendMulti(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet); CanHandle *handle;
static HalStatus sendSingleMultiFrame(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet, uint8_t *offset); MmrCanPacket *packet;
static uint8_t computeFramesToSend(MmrCanPacket *packet);
static uint8_t computeNextMessageLength(MmrCanPacket *packet, uint8_t offset);
struct {
CanTxHeader tx;
MmrCanHeader mmr;
} headers;
} TransmissionParams;
static HalStatus send(TransmissionParams *tp);
static HalStatus sendNormal(TransmissionParams *tp);
static HalStatus sendMulti(TransmissionParams *tp);
static HalStatus sendSingleMultiFrame(TransmissionParams *tp);
static uint8_t computeFramesToSend(MmrCanPacket *packet);
static uint8_t computeNextMessageLength(MmrCanPacket *packet);
static void setMessageType(TransmissionParams *header, MmrCanMessageType type);
static void syncHeaders(TransmissionParams *tp);
HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) { HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) {
CanTxHeader header = { TransmissionParams tp = {
.IDE = CAN_ID_EXT, .handle = hcan,
.RTR = CAN_RTR_DATA, .packet = &packet,
.DLC = packet.length, .headers.tx = {
.ExtId = convertTo(uint32_t, packet.header), .IDE = CAN_ID_EXT,
.TransmitGlobalTime = DISABLE, .RTR = CAN_RTR_DATA,
.DLC = packet.length,
.TransmitGlobalTime = DISABLE,
},
}; };
syncHeaders(&tp);
return packet.length <= MMR_CAN_MAX_DATA_LENGTH return packet.length <= MMR_CAN_MAX_DATA_LENGTH
? sendNormal(hcan, &header, &packet) ? sendNormal(&tp)
: sendMulti(hcan, &header, &packet); : sendMulti(&tp);
} }
static HalStatus sendNormal( static HalStatus sendNormal(TransmissionParams *tp) {
CanHandle *hcan, setMessageType(tp, MMR_CAN_MESSAGE_TYPE_NORMAL);
CanTxHeader *header, return send(tp);
MmrCanPacket *packet
) {
header->ExtId |= MMR_CAN_MESSAGE_TYPE_NORMAL;
return
HAL_CAN_AddTxMessage(hcan, header, packet->data, packet->mailbox);
} }
static HalStatus sendMulti( static HalStatus sendMulti(TransmissionParams *tp) {
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet
) {
HalStatus status = HAL_OK; HalStatus status = HAL_OK;
uint8_t offset = 0; uint8_t framesToSend = computeFramesToSend(tp->packet);
uint8_t framesToSend = computeFramesToSend(packet);
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME; setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME);
do { do {
bool isLastFrame = framesToSend <= 1; bool isLastFrame = framesToSend <= 1;
if (isLastFrame) { if (isLastFrame) {
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END; setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END);
} }
status |= status |= sendSingleMultiFrame(tp);
sendSingleMultiFrame(hcan, header, packet, &offset);
} }
while (framesToSend-- > 1 && status == HAL_OK); while (framesToSend-- > 1 && status == HAL_OK);
@@ -61,19 +67,32 @@ static HalStatus sendMulti(
} }
static HalStatus sendSingleMultiFrame( static HalStatus sendSingleMultiFrame(TransmissionParams *tp) {
CanHandle *hcan, uint8_t length =
CanTxHeader *header, computeNextMessageLength(tp->packet);
MmrCanPacket *packet,
uint8_t *offset
) {
uint8_t *dataStart = packet->data + (*offset);
uint8_t length = computeNextMessageLength(packet, *offset);
header->DLC = length; tp->packet->length -= length;
*offset += length; tp->packet->data += length;
tp->headers.tx.DLC = length;
return HAL_CAN_AddTxMessage(hcan, header, dataStart, packet->mailbox); return send(tp);
}
static HalStatus send(TransmissionParams *tp) {
syncHeaders(tp);
return HAL_CAN_AddTxMessage(
tp->handle,
&tp->headers.tx,
tp->packet->data,
tp->packet->mailbox
);
}
static void syncHeaders(TransmissionParams *tp) {
tp->headers.tx.ExtId = *MMR_CAN_HeaderToBits(&tp->headers.mmr);
} }
@@ -109,22 +128,14 @@ static uint8_t computeFramesToSend(MmrCanPacket *packet) {
/** /**
* @brief * @brief
* Returns the length for the next message, either * Returns the length for the next message, either
* 8 bytes or a lower value, keeping the offset into count. * 8 bytes or a lower value.
*
* @example
* Given
* - a 17 bytes packet
* - an offset starting at 0 and supposedly incrementing
* of 8 after each call
*
* Three subsequent calls to this function will return
* First call -> min(17 - 0, 8) = min(17, 8) = 8 (bytes)
* Second call -> min(17 - 8, 8) = min(9, 8) = 8 (bytes)
* Third call -> min(17 - 16, 8) = min(1, 8) = 1 (byte)
*/ */
static uint8_t computeNextMessageLength(MmrCanPacket *packet, uint8_t offset) { static uint8_t computeNextMessageLength(MmrCanPacket *packet) {
uint8_t remainingBytes = packet->length - offset;
return min( return min(
remainingBytes, MMR_CAN_MAX_DATA_LENGTH packet->length, MMR_CAN_MAX_DATA_LENGTH
); );
} }
static always_inline void setMessageType(TransmissionParams *tp, MmrCanMessageType type) {
tp->headers.mmr.messageType = type;
}