WIP
This commit is contained in:
+24
-3
@@ -46,6 +46,15 @@ typedef uint32_t (*MmrCanTickProvider)();
|
||||
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 {
|
||||
bool enabled;
|
||||
|
||||
@@ -115,7 +124,7 @@ typedef struct MmrCanFilterSettings {
|
||||
*/
|
||||
typedef struct MmrCanPacket {
|
||||
MmrCanHeader header;
|
||||
uint8_t *data;
|
||||
void *data;
|
||||
uint8_t length;
|
||||
} MmrCanPacket;
|
||||
|
||||
@@ -173,6 +182,18 @@ typedef struct MmrCanMessage {
|
||||
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
|
||||
* Sets the tick provider.
|
||||
@@ -235,7 +256,7 @@ HalStatus MMR_CAN_SendNoTamper(CanHandle *hcan, MmrCanPacket packet);
|
||||
* @brief
|
||||
* Tries to receive a message.
|
||||
*/
|
||||
MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result);
|
||||
MmrResult MMR_CAN_TryReceive(MmrCan *can, MmrCanMessage *result);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@@ -245,6 +266,6 @@ MmrResult MMR_CAN_TryReceive(CanHandle *hcan, MmrCanMessage *result);
|
||||
* If a multi-frame message is received, this function will block
|
||||
* 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_ */
|
||||
|
||||
@@ -79,7 +79,5 @@ MmrCanHeader MMR_CAN_HeaderFromBits(uint32_t bits);
|
||||
* Tells wether the given header represents an SCS.
|
||||
*/
|
||||
bool MMR_CAN_IsHeaderScs(MmrCanHeader header);
|
||||
bool MMR_CAN_IsMultiFrame(MmrCanHeader header);
|
||||
bool MMR_CAN_IsMultiFrameEnd(MmrCanHeader header);
|
||||
|
||||
#endif /* INC_MMR_CAN_HEADER_H_ */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
typedef uint32_t CanId;
|
||||
typedef uint32_t CanMailbox;
|
||||
typedef uint32_t CanFifo;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
#include "mmr_can_util.h"
|
||||
#include "mmr_can_optimize.h"
|
||||
|
||||
struct MmrCanHeader {
|
||||
|
||||
};
|
||||
|
||||
|
||||
uint32_t MMR_CAN_HeaderToBits(MmrCanHeader header) {
|
||||
return 0
|
||||
| ((uint32_t)header.priority << 26)
|
||||
@@ -25,11 +30,3 @@ MmrCanHeader MMR_CAN_HeaderFromBits(uint32_t bits) {
|
||||
bool MMR_CAN_IsHeaderScs(MmrCanHeader header) {
|
||||
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
@@ -2,25 +2,7 @@
|
||||
#include "mmr_can.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
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) {
|
||||
MmrResult MMR_CAN_TryReceive(MmrCan *can, MmrCanMessage *result) {
|
||||
size_t pendingMessages =
|
||||
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) {
|
||||
ReceptionParams rp = {
|
||||
.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 MMR_CAN_Receive(MmrCan *can, MmrCanMessage *result) {
|
||||
CanRxHeader rxHeader = {};
|
||||
HalStatus status = HAL_CAN_GetRxMessage(
|
||||
rp->handle,
|
||||
rp->fifo,
|
||||
&rp->headers.rx,
|
||||
rp->result
|
||||
can->handle,
|
||||
can->fifo,
|
||||
&rxHeader,
|
||||
result->store
|
||||
);
|
||||
|
||||
rp->headers.mmr = MMR_CAN_HeaderFromBits(rp->headers.rx.ExtId);
|
||||
result->header = MMR_CAN_HeaderFromBits(rxHeader.ExtId);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static bool headerIsMultiFrame(MmrCanHeader header, CanId targetId) {
|
||||
return
|
||||
MMR_CAN_IsMultiFrame(header) &&
|
||||
!MMR_CAN_IsMultiFrameEnd(header) &&
|
||||
header.senderId == targetId;
|
||||
}
|
||||
|
||||
+54
-155
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user