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_send.c
T
Stefano Calabretti 7b09401b00 Multiple frames implementation (#2)
* Add rx event handlers

* Fix compile errors and add constness

* Pass sender id

* Change api interface

* Revert changes

* Add filter fifo

* Add default setup

* Add receive function

* Remove interrupt activation

* Activate RX interrupts

* Merge remote changes

* Add event list constructor

* Fix compilation bug

* Send and receive multiple frames

* Refactor

* Refactor

* Fix compile error

* Use known syntax

* Refactor

* Provide storage

* Add frame end

* Add some documentation

* Turn macros into functions

* Refactor

* Refactor

* Fix compile error

* Use ExtendedIds

Co-authored-by: Riccardo998 <riccardo.storchi98@gmail.com>
2021-12-09 11:39:39 +01:00

131 lines
3.5 KiB
C

#include <stdbool.h>
#include "mmr_can.h"
#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);
HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) {
CanTxHeader header = {
.IDE = CAN_ID_EXT,
.RTR = CAN_RTR_DATA,
.DLC = packet.length,
.ExtId = packet.remoteId << 5,
.TransmitGlobalTime = DISABLE,
};
return packet.length <= MMR_CAN_MAX_DATA_LENGTH
? sendNormal(hcan, &header, &packet)
: sendMulti(hcan, &header, &packet);
}
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 sendMulti(
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet
) {
HalStatus status = HAL_OK;
uint8_t offset = 0;
uint8_t framesToSend = computeFramesToSend(packet);
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME;
do {
bool isLastFrame = framesToSend <= 1;
if (isLastFrame) {
header->ExtId |= MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END;
}
status |=
sendSingleMultiFrame(hcan, header, packet, &offset);
}
while (framesToSend-- > 1 && status == HAL_OK);
return status;
}
static HalStatus sendSingleMultiFrame(
CanHandle *hcan,
CanTxHeader *header,
MmrCanPacket *packet,
uint8_t *offset
) {
uint8_t *dataStart = packet->data + (*offset);
uint8_t length = computeNextMessageLength(packet, *offset);
header->DLC = length;
*offset += length;
return HAL_CAN_AddTxMessage(hcan, header, dataStart, packet->mailbox);
}
/**
* @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, 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)
*/
static uint8_t computeNextMessageLength(MmrCanPacket *packet, uint8_t offset) {
uint8_t remainingBytes = packet->length - offset;
return min(
remainingBytes, MMR_CAN_MAX_DATA_LENGTH
);
}