This commit is contained in:
Stefano Calabretti
2022-05-17 14:17:50 +02:00
parent 21ace4efb4
commit f34e2a1fc6
6 changed files with 92 additions and 237 deletions
+24 -3
View File
@@ -46,6 +46,15 @@ typedef uint32_t (*MmrCanTickProvider)();
typedef uint8_t CanRxBuffer[MMR_CAN_MAX_DATA_LENGTH]; typedef uint8_t CanRxBuffer[MMR_CAN_MAX_DATA_LENGTH];
typedef struct MmrCan {
CanId id;
CanHandle *handle;
CanFifo fifo;
CanMailbox mailboxes[MAILBOXES_COUNT];
uint8_t currentMailbox;
} MmrCan;
typedef struct MmrCanFilterSettings { typedef struct MmrCanFilterSettings {
bool enabled; bool enabled;
@@ -115,7 +124,7 @@ typedef struct MmrCanFilterSettings {
*/ */
typedef struct MmrCanPacket { typedef struct MmrCanPacket {
MmrCanHeader header; MmrCanHeader header;
uint8_t *data; void *data;
uint8_t length; uint8_t length;
} MmrCanPacket; } MmrCanPacket;
@@ -173,6 +182,18 @@ typedef struct MmrCanMessage {
extern MmrCanTickProvider __mmr_can_tickProvider; extern MmrCanTickProvider __mmr_can_tickProvider;
MmrCan MMR_CAN_Create(CanHandle *hcan, CanFifo rxFifo);
HalStatus MMR_CAN_Start(MmrCan *can);
HalStatus MMR_CAN_EnableFilter(MmrCan *can, CanFilterMask mask, CanFilterBank bank);
HalStatus MMR_CAN_SendString(MmrCan *can, MmrCanMessageId msgId, const char *data);
HalStatus MMR_CAN_SendInt(MmrCan *can, MmrCanMessageId msgId, int data);
HalStatus MMR_CAN_SendFloat(MmrCan *can, MmrCanMessageId msgId, float data);
HalStatus MMR_CAN_SendRaw(MmrCan *can, MmrCanMessageId msgId, void *data, uint8_t length);
HalStatus MMR_CAN_SendPacket(MmrCan *can, MmrCanPacket packet);
/** /**
* @brief * @brief
* Sets the tick provider. * Sets the tick provider.
@@ -235,7 +256,7 @@ HalStatus MMR_CAN_SendNoTamper(CanHandle *hcan, MmrCanPacket packet);
* @brief * @brief
* Tries to receive a message. * Tries to receive a message.
*/ */
MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result); MmrResult MMR_CAN_TryReceive(MmrCan *can, MmrCanMessage *result);
/** /**
* @brief * @brief
@@ -245,6 +266,6 @@ MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result);
* If a multi-frame message is received, this function will block * If a multi-frame message is received, this function will block
* and read every frame for that particular message. * and read every frame for that particular message.
*/ */
HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result); HalStatus MMR_CAN_Receive(MmrCan *can, MmrCanMessage *result);
#endif /* INC_MMR_CAN_H_ */ #endif /* INC_MMR_CAN_H_ */
-2
View File
@@ -79,7 +79,5 @@ MmrCanHeader MMR_CAN_HeaderFromBits(uint32_t bits);
* Tells wether the given header represents an SCS. * Tells wether the given header represents an SCS.
*/ */
bool MMR_CAN_IsHeaderScs(MmrCanHeader header); bool MMR_CAN_IsHeaderScs(MmrCanHeader header);
bool MMR_CAN_IsMultiFrame(MmrCanHeader header);
bool MMR_CAN_IsMultiFrameEnd(MmrCanHeader header);
#endif /* INC_MMR_CAN_HEADER_H_ */ #endif /* INC_MMR_CAN_HEADER_H_ */
+1
View File
@@ -12,6 +12,7 @@
typedef uint32_t CanId; typedef uint32_t CanId;
typedef uint32_t CanMailbox; typedef uint32_t CanMailbox;
typedef uint32_t CanFifo;
/** /**
* @brief * @brief
+5 -8
View File
@@ -2,6 +2,11 @@
#include "mmr_can_util.h" #include "mmr_can_util.h"
#include "mmr_can_optimize.h" #include "mmr_can_optimize.h"
struct MmrCanHeader {
};
uint32_t MMR_CAN_HeaderToBits(MmrCanHeader header) { uint32_t MMR_CAN_HeaderToBits(MmrCanHeader header) {
return 0 return 0
| ((uint32_t)header.priority << 26) | ((uint32_t)header.priority << 26)
@@ -25,11 +30,3 @@ MmrCanHeader MMR_CAN_HeaderFromBits(uint32_t bits) {
bool MMR_CAN_IsHeaderScs(MmrCanHeader header) { bool MMR_CAN_IsHeaderScs(MmrCanHeader header) {
return header.messageType == MMR_CAN_MESSAGE_TYPE_SCS; return header.messageType == MMR_CAN_MESSAGE_TYPE_SCS;
} }
bool MMR_CAN_IsMultiFrame(MmrCanHeader header) {
return header.messageType == MMR_CAN_MESSAGE_TYPE_MULTI_FRAME;
}
bool MMR_CAN_IsMultiFrameEnd(MmrCanHeader header) {
return header.messageType == MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END;
}
+8 -69
View File
@@ -2,25 +2,7 @@
#include "mmr_can.h" #include "mmr_can.h"
typedef struct { MmrResult MMR_CAN_TryReceive(MmrCan *can, MmrCanMessage *result) {
CanHandle *handle;
uint8_t *result;
struct {
CanRxHeader rx;
MmrCanHeader mmr;
} headers;
uint8_t fifo;
} ReceptionParams;
static HalStatus receiveOne(ReceptionParams *rp);
static HalStatus receiveAll(ReceptionParams *rp);
static bool headerIsMultiFrame(MmrCanHeader header, CanId targetId);
MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result) {
size_t pendingMessages = size_t pendingMessages =
HAL_CAN_GetRxFifoFillLevel(hcan, MMR_CAN_RX_FIFO); HAL_CAN_GetRxFifoFillLevel(hcan, MMR_CAN_RX_FIFO);
@@ -34,58 +16,15 @@ MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result) {
} }
HalStatus MMR_CAN_Receive(CanHandle *hcan, MmrCanMessage *result) { HalStatus MMR_CAN_Receive(MmrCan *can, MmrCanMessage *result) {
ReceptionParams rp = { CanRxHeader rxHeader = {};
.handle = hcan,
.result = (uint8_t*)result->store,
.fifo = MMR_CAN_RX_FIFO,
};
HalStatus status = receiveOne(&rp);
if (status != HAL_OK) {
return status;
}
result->header = rp.headers.mmr;
if (MMR_CAN_IsMultiFrame(rp.headers.mmr)) {
status |= receiveAll(&rp);
}
return status;
}
static HalStatus receiveAll(ReceptionParams *rp) {
CanId targetId = rp->headers.mmr.senderId;
HalStatus status = HAL_OK;
do {
rp->result += MMR_CAN_MAX_DATA_LENGTH;
status |= receiveOne(rp);
}
while (
headerIsMultiFrame(rp->headers.mmr, targetId) && status == HAL_OK
);
return status;
}
static HalStatus receiveOne(ReceptionParams *rp) {
HalStatus status = HAL_CAN_GetRxMessage( HalStatus status = HAL_CAN_GetRxMessage(
rp->handle, can->handle,
rp->fifo, can->fifo,
&rp->headers.rx, &rxHeader,
rp->result result->store
); );
rp->headers.mmr = MMR_CAN_HeaderFromBits(rp->headers.rx.ExtId); result->header = MMR_CAN_HeaderFromBits(rxHeader.ExtId);
return status; return status;
} }
static bool headerIsMultiFrame(MmrCanHeader header, CanId targetId) {
return
MMR_CAN_IsMultiFrame(header) &&
!MMR_CAN_IsMultiFrameEnd(header) &&
header.senderId == targetId;
}
+54 -155
View File
@@ -2,174 +2,73 @@
#include "mmr_can.h" #include "mmr_can.h"
#include "mmr_can_util.h" #include "mmr_can_util.h"
typedef struct {
CanHandle *handle;
MmrCanPacket *packet;
struct {
CanTxHeader tx;
MmrCanHeader mmr;
} headers;
} TransmissionParams;
static TransmissionParams buildParams(CanHandle *hcan, MmrCanPacket *packet);
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);
static CanMailbox *getNextMailbox();
#define MAILBOXES_COUNT 3 #define MAILBOXES_COUNT 3
static CanMailbox __mailboxes[MAILBOXES_COUNT] = {}; static MmrCanHeader buildDefaultHeader(MmrCan *can, MmrCanMessageId msgId);
static uint8_t __currentMailbox = 0; static CanMailbox *getNextMailbox(MmrCan *can);
HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) { HalStatus MMR_CAN_SendString(MmrCan *can, MmrCanMessageId msgId, const char *data) {
TransmissionParams tp = uint8_t len =
buildParams(hcan, &packet); strnlen(data, MMR_CAN_MAX_DATA_LENGTH);
syncHeaders(&tp); return MMR_CAN_SendRaw(can, msgId, &data, len);
return packet.length <= MMR_CAN_MAX_DATA_LENGTH }
? sendNormal(&tp)
: sendMulti(&tp); HalStatus MMR_CAN_SendInt(MmrCan *can, MmrCanMessageId msgId, int data) {
return MMR_CAN_SendRaw(can, msgId, &data, sizeof(data))
}
HalStatus MMR_CAN_SendFloat(MmrCan *can, MmrCanMessageId msgId, float data) {
return MMR_CAN_SendRaw(can, msgId, &data, sizeof(data));
} }
HalStatus MMR_CAN_SendNoTamper(CanHandle *hcan, MmrCanPacket packet) { HalStatus MMR_CAN_SendRaw(
TransmissionParams tp = MmrCan *can,
buildParams(hcan, &packet); MmrCanMessageId msgId,
void *data,
return send(&tp); uint8_t length
) {
return MMR_CAN_SendPacket(can, (MmrCanPacket){
.header = buildDefaultHeader(can, msgId),
.data = data,
.length = length,
});
} }
static TransmissionParams buildParams(CanHandle *hcan, MmrCanPacket *packet) { HalStatus MMR_CAN_SendPacket(MmrCan *can, MmrCanPacket packet) {
return (TransmissionParams) { CanTxHeader txHeader = {
.handle = hcan, .ExtId = MMR_CAN_HeaderToBits(packet.header),
.packet = packet, .IDE = CAN_ID_EXT,
.headers.mmr = packet->header, .RTR = CAN_RTR_DATA,
.headers.tx = { .DLC = packet->length,
.IDE = CAN_ID_EXT, .TransmitGlobalTime = DISABLE,
.RTR = CAN_RTR_DATA, };
.DLC = packet->length,
.TransmitGlobalTime = DISABLE, return HAL_CAN_AddTxMessage(
}, can->handle,
&txHeader,
(uint8_t*)packet.data,
getNextMailbox(can)
);
}
MmrCanHeader buildDefaultHeader(MmrCan *can, MmrCanMessageId msgId) {
return (MmrCanHeader){
.messageId = msgId,
.senderId = can->id,
.priority = MMR_CAN_MESSAGE_PRIORITY_NORMAL,
.messageType = MMR_CAN_MESSAGE_TYPE_NORMAL,
}; };
} }
static HalStatus sendNormal(TransmissionParams *tp) { static CanMailbox *getNextMailbox(MmrCan *can) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_NORMAL); can->currentMailbox++;
return send(tp); can->currentMailbox %= MAILBOXES_COUNT;
}
return can->mailboxes + can->currentMailbox;
static HalStatus sendMulti(TransmissionParams *tp) {
HalStatus status = HAL_OK;
uint8_t framesToSend = computeFramesToSend(tp->packet);
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME);
do {
bool isLastFrame = framesToSend <= 1;
if (isLastFrame) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END);
}
status |= sendSingleMultiFrame(tp);
}
while (framesToSend-- > 1 && status == HAL_OK);
return status;
}
static HalStatus sendSingleMultiFrame(TransmissionParams *tp) {
uint8_t length =
computeNextMessageLength(tp->packet);
tp->headers.tx.DLC = length;
tp->packet->length -= length;
HalStatus result = send(tp);
tp->packet->data += length;
return result;
}
static HalStatus send(TransmissionParams *tp) {
syncHeaders(tp);
return HAL_CAN_AddTxMessage(
tp->handle,
&tp->headers.tx,
tp->packet->data,
getNextMailbox()
);
}
static CanMailbox *getNextMailbox() {
__currentMailbox++;
__currentMailbox %= MAILBOXES_COUNT;
return __mailboxes + __currentMailbox;
}
static void syncHeaders(TransmissionParams *tp) {
tp->headers.tx.ExtId = MMR_CAN_HeaderToBits(tp->headers.mmr);
}
/**
* @brief
* Computes the frames that will need to be sent for a packet.
*
* For example, if a packet has 15 bytes, the function will return
* 2, as one packet is needed for the first 8 bytes and another is
* needed for the remaining 7.
*
* @example
* The computation is pretty simple
* Given
* length = 17 (bytes)
* We'll have
* framesToSend = 17 / 8 = 2 (frames)
* remainder = 17 % 8 = 1 (bytes)
* maybeOneForRemainder = 1 > 0 = 1 (frame)
* -------------------------------------------
* result = 2 + 1 = 3 (frames)
*/
static uint8_t computeFramesToSend(MmrCanPacket *packet) {
uint8_t length = packet->length;
uint8_t framesToSend = length / MMR_CAN_MAX_DATA_LENGTH;
uint8_t remainder = length % MMR_CAN_MAX_DATA_LENGTH;
uint8_t maybeOneForRemainder = remainder > 0;
return framesToSend + maybeOneForRemainder;
}
/**
* @brief
* Returns the length for the next message, either
* 8 bytes or a lower value.
*/
static uint8_t computeNextMessageLength(MmrCanPacket *packet) {
return min(
packet->length, MMR_CAN_MAX_DATA_LENGTH
);
}
static always_inline void setMessageType(TransmissionParams *tp, MmrCanMessageType type) {
tp->headers.mmr.messageType = type;
} }