Add documentation

This commit is contained in:
Stefano Calabretti
2022-02-15 19:33:22 +01:00
parent 2469d96127
commit 4ac0afc010
7 changed files with 164 additions and 12 deletions
+68 -1
View File
@@ -66,6 +66,43 @@ typedef struct {
} MmrCanFilterSettings; } MmrCanFilterSettings;
/**
* @brief
* A packet that can be sent over a CAN
* network.
*
* @example
* typedef struct {
* int x;
* int y;
* } Point;
*
* HalStatus send(Point point) {
* static CanMailbox mailbox = 0;
*
* MmrCanPacket packet = {
* .header = {
* .priority = MMR_CAN_MESSAGE_PRIORITY_NORMAL,
* .messageId = MMR_CAN_EXAMPLES_POINT,
* .senderId = 0xXXX,
* },
* .mailbox = &mailbox,
* .data = (uint8_t*)&point,
* .length = sizeof(point),
* };
*
* return MMR_CAN_Send(&hcan, packet);
* }
*
* int main() {
* Point p = {10, 20};
* if (send(p) != HAL_OK) {
* Error_Handler();
* }
*
* // 'p' has been sent.
* }
*/
typedef struct { typedef struct {
MmrCanHeader header; MmrCanHeader header;
CanMailbox *mailbox; CanMailbox *mailbox;
@@ -76,7 +113,37 @@ typedef struct {
/** /**
* @brief * @brief
* Represents a CAN message * A message received over a CAN network.
*
* @example
* typedef struct {
* int x;
* int y;
* } Point;
*
* HalStatus receive(Point *result) {
* MmrCanMessage message = {
* .store = result,
* };
*
* HalStatus result = MMR_CAN_Receive(&hcan, &message);
* bool isAPoint = message.header.messageId == MMR_CAN_EXAMPLES_POINT;
* if (!isAPoint) {
* return HAL_ERROR;
* }
*
* return result;
* }
*
* int main() {
* Point p = {};
* if (receive(&p) != HAL_OK) {
* Error_Handler();
* }
*
* // here 'p' has been populated and can
* // be used.
* }
*/ */
typedef struct { typedef struct {
MmrCanHeader header; MmrCanHeader header;
+16 -4
View File
@@ -12,11 +12,10 @@
* portion of the CAN bus message (that is, the lower 5 bits * portion of the CAN bus message (that is, the lower 5 bits
* of the standard id) * of the standard id)
* *
* They are used to check if a message is either standalone * They are used to check if a message is either standalone, an
* or split into multiple frames * acknowledgement or split into multiple frames
* *
* When the priority and id fields are the same, multi-frame * Constants with lower values have an higher priority.
* messages have a higher priority over normal ones
*/ */
typedef enum { typedef enum {
MMR_CAN_MESSAGE_ACK = B_(0001), MMR_CAN_MESSAGE_ACK = B_(0001),
@@ -47,7 +46,20 @@ typedef struct {
} MmrCanHeader; } MmrCanHeader;
/**
* @brief
* Converts an MmrCanHeader to bits.
* That is, a 32bits integer with the first
* 3 bits set to zero and the remaining 29 containing the
* extended id
*/
uint32_t *MMR_CAN_HeaderToBits(MmrCanHeader *header); uint32_t *MMR_CAN_HeaderToBits(MmrCanHeader *header);
/**
* @brief
* Converts a 32bits integer to an MmrCanHeader.
* The left-most 3 bits must be of padding.
*/
MmrCanHeader *MMR_CAN_HeaderFromBits(uint32_t *bits); MmrCanHeader *MMR_CAN_HeaderFromBits(uint32_t *bits);
bool MMR_CAN_IsMultiFrame(MmrCanHeader *header); bool MMR_CAN_IsMultiFrame(MmrCanHeader *header);
+24
View File
@@ -24,10 +24,34 @@ typedef enum {
} MmrCanMessageIdType; } MmrCanMessageIdType;
/**
* @brief
* Returns the 3 bits representing
* the MmrCanMessageIdType.
*/
uint8_t MMR_CAN_GetMessageIdType(MmrCanMessageId msgId); uint8_t MMR_CAN_GetMessageIdType(MmrCanMessageId msgId);
/**
* @brief
* Returns the 7 bits representing
* the message id's subtype.
*/
uint8_t MMR_CAN_GetMessageIdSubtype(MmrCanMessageId msgId); uint8_t MMR_CAN_GetMessageIdSubtype(MmrCanMessageId msgId);
/**
* @brief
* Tells wether the provided message
* is of the given id type.
*
* E.g. if a message is an SCS.
*/
bool MMR_CAN_IsMessageIdOfType(MmrCanMessageId msgId, MmrCanMessageIdType type); bool MMR_CAN_IsMessageIdOfType(MmrCanMessageId msgId, MmrCanMessageIdType type);
/**
* @brief
* Tells wether the given message id is
* represents an SCS.
*/
bool MMR_CAN_IsMessageIdSCS(MmrCanMessageId msgId); bool MMR_CAN_IsMessageIdSCS(MmrCanMessageId msgId);
+10
View File
@@ -2,6 +2,16 @@
#define INC_MMR_CAN_OPTIMIZE_H_ #define INC_MMR_CAN_OPTIMIZE_H_
#ifdef __GNUC__ #ifdef __GNUC__
/**
* @brief
* Tells the compiler that the given method
* must always be inlined.
*
* @example
* static always_inline int min(int a, int b) {
* return a < b ? a : b;
* }
*/
#define always_inline inline __attribute__((always_inline)) #define always_inline inline __attribute__((always_inline))
#else #else
#define always_inline inline #define always_inline inline
+1 -1
View File
@@ -41,7 +41,7 @@ typedef struct {
/** /**
* All time units are to be considered as microseconds ( 1ms ) * All time units are to be considered as milliseconds (1ms)
*/ */
bool MMR_CAN_ClearTimerSCS(MmrCanMessageId scsId, CanId receiverId); bool MMR_CAN_ClearTimerSCS(MmrCanMessageId scsId, CanId receiverId);
bool MMR_CAN_SetTimerSCS(MmrCanMessageId scsId, CanId receiverId, TimerRange currentTime); bool MMR_CAN_SetTimerSCS(MmrCanMessageId scsId, CanId receiverId, TimerRange currentTime);
+3
View File
@@ -8,6 +8,7 @@ typedef uint32_t CanId;
typedef uint32_t CanMailbox; typedef uint32_t CanMailbox;
/** /**
* @brief
* A filter mask for the CANbus. * A filter mask for the CANbus.
* It acts like a subnet mask, filtering the ids that * It acts like a subnet mask, filtering the ids that
* do not match it. * do not match it.
@@ -20,12 +21,14 @@ typedef uint32_t CanMailbox;
typedef uint32_t CanFilterMask; typedef uint32_t CanFilterMask;
/** /**
* @brief
* Stores a value from CAN_filter_FIFO * Stores a value from CAN_filter_FIFO
* That is, CAN_FILTER_FIFOx * That is, CAN_FILTER_FIFOx
*/ */
typedef uint8_t CanFilterFifo; typedef uint8_t CanFilterFifo;
/** /**
* @brief
* Represents a filter bank. * Represents a filter bank.
* The values must be in the range [0, 27] * The values must be in the range [0, 27]
*/ */
+39 -3
View File
@@ -4,16 +4,52 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
/**
* @brief
* Returns the size of the given array.
*
* This only works on static arrays declared
* within the current scope, that is:
* int main() {
* int arr[] = {1, 2, 3};
* int len = sizeofarray(arr);
* }
*/
#define sizeofarray(array) \ #define sizeofarray(array) \
(sizeof(array) / sizeof(*(array))) (sizeof(array) / sizeof(*(array)))
/**
* @brief
* Returns the length of a statically, non const ptr, declared
* string.
* That is:
* int main() {
* char str[] = "abc";
* int len = stringArrayLength(str);
* }
*/
#define stringArrayLength(array) \ #define stringArrayLength(array) \
stringBufferLength((array), sizeofarray(array)) stringBufferLength((array), sizeofarray(array))
/**
* @brief
* Returns the length of a string buffer.
* Its format must be in bytes, so it could be:
* const char*
* char*
* uint8_t*
* etc...
*/
#define stringBufferLength(pbuffer, maxLen) \ #define stringBufferLength(pbuffer, maxLen) \
strnlen((const char*)(pbuffer), maxLen) strnlen((const char*)(pbuffer), maxLen)
#define min(a, b) ((a) < (b) ? a : b); /**
* @brief
* Returns the minimum between the
* two given values.
* E.g. min(1, 2) == 1 // true
*/
#define min(a, b) ((a) < (b) ? a : b)
#define mask(value, bits) (value & bits) #define mask(value, bits) (value & bits)
#define convertTo(resultType, lvalue) (*interpretAs(resultType*, &(lvalue))) #define convertTo(resultType, lvalue) (*interpretAs(resultType*, &(lvalue)))
#define interpretAs(resultType, lvalue) ((resultType)(lvalue)) #define interpretAs(resultType, lvalue) ((resultType)(lvalue))
@@ -26,10 +62,10 @@
* Either * Either
* - Error: the computation resulted in error * - Error: the computation resulted in error
* - Pending: the computation is still undergoing * - Pending: the computation is still undergoing
* - Completed: the computation has completed succesfully * - Completed: the computation has completed successfully
* and its results can be read * and its results can be read
* *
* Asynchronous logig can be easily implemented using State Machines * Asynchronous logic can be easily implemented using State Machines
*/ */
typedef enum { typedef enum {
MMR_ASYNC_RESULT_ERROR, MMR_ASYNC_RESULT_ERROR,