To run FDCAN filters, I suggest:
1. Add the RXGFC variable to the CANConfig structure. Because write access by the bits is possible only when the bit 1 [CCE] and bit 0 [INIT] of CCCR register are set to 1. And eventually add definition:
Code: Select all
#define FDCAN_SET_RXGFC_LSS(value) (value << FDCAN_RXGFC_LSS_Pos)
#define FDCAN_SET_RXGFC_LSE(value) (value << FDCAN_RXGFC_LSE_Pos)
#define FDCAN_SET_RXGFC_ANFS(value) (value << FDCAN_RXGFC_ANFS_Pos)
#define FDCAN_SET_RXGFC_ANFE(value) (value << FDCAN_RXGFC_ANFE_Pos)
#define FDCAN_SET_RXGFC_RRFS(value) (value << FDCAN_RXGFC_RRFS_Pos)
#define FDCAN_SET_RXGFC_RRFE(value)(value << FDCAN_RXGFC_RRFE_Pos)
But stm32h7xx has not FDCAN_SET_RXGFC_LSS and FDCAN_SET_RXGFC_LSE.
2. To make filter configuration similar to previous versions of CAN drivers:
Code: Select all
typedef struct {
/**
* @brief Filter scale.
* @note This bit associated to this
* filter (0=16 bits mode, 1=32 bits mode).
*/
uint32_t scale:1;
/**
* @brief Number of the filter to be programmed.
*/
uint32_t filter;
/**
* @brief Filter Type.
*/
union {
/**
* @brief Standard filter type.
* @note – 00: Range filter from SFID1 to SFID2
* – 01: Dual ID filter for SFID1 or SFID2
* – 10: Classic filter: SFID1 = filter, SFID2 = mask
* – 11: Filter element disabled
*/
uint8_t SFT:2;
/**
* @brief Extended filter type.
* @note – 00: Range filter from EF1ID to EF2ID (EF2ID >= EF1ID)
* – 01: Dual ID filter for EF1ID or EF2ID
* – 10: Classic filter: EF1ID = filter, EF2ID = mask
* – 11: Range filter from EF1ID to EF2ID (EF2ID >= EF1ID), XIDAM mask not applied
*/
uint8_t EFT:2;
};
/**
* @brief Standard or Extended filter element configuration.
* @note – 000: Disable filter element
* – 001: Store in Rx FIFO 0 if filter matches
* – 010: Store in Rx FIFO 1 if filter matches
* – 011: Reject ID if filter matches
* – 100: Set priority if filter matches
* – 101: Set priority and store in FIFO 0 if filter matches
* – 110: Set priority and store in FIFO 1 if filter matches
* – 111: Not used
*/
union {
uint8_t SFEC:3;
uint8_t EFEC:3;
};
/**
* @brief Standard or Extended filter ID 1 (identifier).
*/
union {
uint16_t SFID1:11;
uint32_t EFID1:29;
};
/**
* @brief Standard or Extended filter ID 2. (mask/identifier depending on mode=0/1).
*/
union {
uint16_t SFID2:11;
uint32_t EFID2:29;
};
} CANFilter;
And function:
Code: Select all
static void can_lld_set_filters(CANDriver* canp,
uint32_t can2sb,
uint32_t num,
const CANFilter *cfp) {
(void) can2sb;
if (num > 0) {
uint32_t filter_field1;
uint32_t filter_field2;
uint32_t *filter_address;
for (size_t i = 0; i < num; i++) {
if (cfp->scale == 0) {
osalDbgCheck(cfp->filter <= STM32_FDCAN_FLS_NBR);
filter_field1 = ((cfp->SFT << 30U) | (cfp->SFEC << 27U) |
(cfp->SFID1 << 16U) | cfp->SFID2);
/* Calculate filter address */
filter_address = (uint32_t *)(canp->ram_base + SRAMCAN_FLSSA + (cfp->filter * SRAMCAN_FLS_SIZE));
/* Write filter element to the message RAM */
*filter_address = filter_field1;
}
else {
osalDbgCheck(cfp->filter <= STM32_FDCAN_FLE_NBR);
/* Build first word of filter element */
filter_field1 = ((cfp->EFEC << 29U) | cfp->EFID1);
/* Build second word of filter element */
filter_field2 = ((cfp->EFT << 30U) | cfp->EFID2);
/* Calculate filter address */
filter_address = (uint32_t *)(canp->ram_base + SRAMCAN_FLESA + (cfp->filter * SRAMCAN_FLS_SIZE));
/* Write filter element to the message RAM */
*filter_address = filter_field1;
filter_address++;
*filter_address = filter_field2;
}
cfp++;
}
}
}
Code: Select all
void canSTM32SetFilters(CANDriver *canp, uint32_t can2sb,
uint32_t num, const CANFilter *cfp) {
osalDbgAssert(canp->state == CAN_READY, "invalid state");
can_lld_set_filters(canp, can2sb, num, cfp);
}
I'm tested this on stm32g474