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
+54 -155
View File
@@ -2,174 +2,73 @@
#include "mmr_can.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
static CanMailbox __mailboxes[MAILBOXES_COUNT] = {};
static uint8_t __currentMailbox = 0;
static MmrCanHeader buildDefaultHeader(MmrCan *can, MmrCanMessageId msgId);
static CanMailbox *getNextMailbox(MmrCan *can);
HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) {
TransmissionParams tp =
buildParams(hcan, &packet);
HalStatus MMR_CAN_SendString(MmrCan *can, MmrCanMessageId msgId, const char *data) {
uint8_t len =
strnlen(data, MMR_CAN_MAX_DATA_LENGTH);
syncHeaders(&tp);
return packet.length <= MMR_CAN_MAX_DATA_LENGTH
? sendNormal(&tp)
: sendMulti(&tp);
return MMR_CAN_SendRaw(can, msgId, &data, len);
}
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) {
TransmissionParams tp =
buildParams(hcan, &packet);
return send(&tp);
HalStatus MMR_CAN_SendRaw(
MmrCan *can,
MmrCanMessageId msgId,
void *data,
uint8_t length
) {
return MMR_CAN_SendPacket(can, (MmrCanPacket){
.header = buildDefaultHeader(can, msgId),
.data = data,
.length = length,
});
}
static TransmissionParams buildParams(CanHandle *hcan, MmrCanPacket *packet) {
return (TransmissionParams) {
.handle = hcan,
.packet = packet,
.headers.mmr = packet->header,
.headers.tx = {
.IDE = CAN_ID_EXT,
.RTR = CAN_RTR_DATA,
.DLC = packet->length,
.TransmitGlobalTime = DISABLE,
},
HalStatus MMR_CAN_SendPacket(MmrCan *can, MmrCanPacket packet) {
CanTxHeader txHeader = {
.ExtId = MMR_CAN_HeaderToBits(packet.header),
.IDE = CAN_ID_EXT,
.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) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_NORMAL);
return send(tp);
}
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;
static CanMailbox *getNextMailbox(MmrCan *can) {
can->currentMailbox++;
can->currentMailbox %= MAILBOXES_COUNT;
return can->mailboxes + can->currentMailbox;
}