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
*/
typedef struct {
CanId senderId;
MmrCanHeader header;
void *store;
} MmrCanMessage;
+14 -2
View File
@@ -24,18 +24,30 @@ typedef enum {
} 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
* This struct encodes the values stored inside the
* extended id field of a CAN packet.
*/
typedef struct {
uint32_t priority : 5;
uint32_t senderId : 23;
MmrCanMessagePriority priority : 3;
uint32_t dictionaryEntry : 10;
uint32_t senderId : 12;
MmrCanMessageType messageType : 4;
} MmrCanHeader;
uint32_t *MMR_CAN_HeaderToBits(MmrCanHeader *header);
MmrCanHeader *MMR_CAN_HeaderFromBits(uint32_t *bits);
bool MMR_CAN_IsMultiFrame(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_util.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) {
return header->messageType == MMR_CAN_MESSAGE_TYPE_MULTI_FRAME;
+10 -8
View File
@@ -1,14 +1,11 @@
#include <stdbool.h>
#include "mmr_can.h"
static HalStatus receiveOne(ReceptionParams *rp);
static HalStatus receiveAll(ReceptionParams *rp);
static bool headerIsMultiFrame(MmrCanHeader *header, CanId targetId);
typedef struct {
CanHandle *handle;
uint8_t *result;
struct {
CanRxHeader rx;
MmrCanHeader mmr;
@@ -18,6 +15,11 @@ typedef struct {
} ReceptionParams;
static HalStatus receiveOne(ReceptionParams *rp);
static HalStatus receiveAll(ReceptionParams *rp);
static bool headerIsMultiFrame(MmrCanHeader *header, CanId targetId);
/**
* @brief
* Reads a CAN message and stores it inside the
@@ -29,7 +31,7 @@ typedef struct {
HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) {
ReceptionParams rp = {
.handle = hcan,
.result = interpretAs(uint8_t*, result->store),
.result = (uint8_t*)result->store,
.fifo = MMR_CAN_RX_FIFO,
};
@@ -38,7 +40,7 @@ HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) {
return status;
}
result->senderId = rp.headers.mmr.senderId;
result->header = rp.headers.mmr;
if (MMR_CAN_IsMultiFrame(&rp.headers.mmr)) {
status |= receiveAll(&rp);
}
@@ -63,9 +65,9 @@ static HalStatus receiveAll(ReceptionParams *rp) {
static HalStatus receiveOne(ReceptionParams *rp) {
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;
}
+69 -58
View File
@@ -3,57 +3,63 @@
#include "mmr_can_util.h"
static HalStatus sendNormal(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet);
static HalStatus sendMulti(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet);
static HalStatus sendSingleMultiFrame(CanHandle *hcan, CanTxHeader *header, MmrCanPacket *packet, uint8_t *offset);
static uint8_t computeFramesToSend(MmrCanPacket *packet);
static uint8_t computeNextMessageLength(MmrCanPacket *packet, uint8_t offset);
typedef struct {
CanHandle *handle;
MmrCanPacket *packet;
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) {
CanTxHeader header = {
.IDE = CAN_ID_EXT,
.RTR = CAN_RTR_DATA,
.DLC = packet.length,
.ExtId = convertTo(uint32_t, packet.header),
.TransmitGlobalTime = DISABLE,
TransmissionParams tp = {
.handle = hcan,
.packet = &packet,
.headers.tx = {
.IDE = CAN_ID_EXT,
.RTR = CAN_RTR_DATA,
.DLC = packet.length,
.TransmitGlobalTime = DISABLE,
},
};
syncHeaders(&tp);
return packet.length <= MMR_CAN_MAX_DATA_LENGTH
? sendNormal(hcan, &header, &packet)
: sendMulti(hcan, &header, &packet);
? sendNormal(&tp)
: sendMulti(&tp);
}
static HalStatus sendNormal(
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet
) {
header->ExtId |= MMR_CAN_MESSAGE_TYPE_NORMAL;
return
HAL_CAN_AddTxMessage(hcan, header, packet->data, packet->mailbox);
static HalStatus sendNormal(TransmissionParams *tp) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_NORMAL);
return send(tp);
}
static HalStatus sendMulti(
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet
) {
static HalStatus sendMulti(TransmissionParams *tp) {
HalStatus status = HAL_OK;
uint8_t offset = 0;
uint8_t framesToSend = computeFramesToSend(packet);
uint8_t framesToSend = computeFramesToSend(tp->packet);
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME;
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME);
do {
bool isLastFrame = framesToSend <= 1;
if (isLastFrame) {
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END;
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END);
}
status |=
sendSingleMultiFrame(hcan, header, packet, &offset);
status |= sendSingleMultiFrame(tp);
}
while (framesToSend-- > 1 && status == HAL_OK);
@@ -61,19 +67,32 @@ static HalStatus sendMulti(
}
static HalStatus sendSingleMultiFrame(
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet,
uint8_t *offset
) {
uint8_t *dataStart = packet->data + (*offset);
uint8_t length = computeNextMessageLength(packet, *offset);
static HalStatus sendSingleMultiFrame(TransmissionParams *tp) {
uint8_t length =
computeNextMessageLength(tp->packet);
header->DLC = length;
*offset += length;
tp->packet->length -= 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
* Returns the length for the next message, either
* 8 bytes or a lower value, keeping the offset into count.
*
* @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)
* 8 bytes or a lower value.
*/
static uint8_t computeNextMessageLength(MmrCanPacket *packet, uint8_t offset) {
uint8_t remainingBytes = packet->length - offset;
static uint8_t computeNextMessageLength(MmrCanPacket *packet) {
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;
}