This repository has been archived on 2026-02-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
can/Src/mmr_can_receive.c
T
2022-02-19 12:59:05 +01:00

85 lines
1.7 KiB
C

#include <stdbool.h>
#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);
/**
* @brief
* Reads a CAN message and stores it inside the
* given MmrCanMessage struct.
*
* 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) {
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 status = HAL_CAN_GetRxMessage(
rp->handle,
rp->fifo,
&rp->headers.rx,
rp->result
);
rp->headers.mmr = MMR_CAN_HeaderFromBits(rp->headers.rx.ExtId);
return status;
}
static always_inline bool headerIsMultiFrame(MmrCanHeader *header, CanId targetId) {
return
MMR_CAN_IsMultiFrame(header) &&
!MMR_CAN_IsMultiFrameEnd(header) &&
header->senderId == targetId;
}