backport fdcan driver

This commit is contained in:
Matthew Kennedy 2021-03-09 01:10:14 -08:00 committed by Andrey
parent ec8358ca7e
commit c4ea154c8f
3 changed files with 113 additions and 51 deletions

View File

@ -134,7 +134,7 @@ static bool fdcan_clock_stop(CANDriver *canp) {
canp->fdcan->CCCR |= FDCAN_CCCR_CSR; canp->fdcan->CCCR |= FDCAN_CCCR_CSR;
start = osalOsGetSystemTimeX(); start = osalOsGetSystemTimeX();
end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS)); end = osalTimeAddX(start, TIME_MS2I(TIMEOUT_INIT_MS));
while ((canp->fdcan->CCCR & FDCAN_CCCR_CSA) != 0U) { while ((canp->fdcan->CCCR & FDCAN_CCCR_CSA) == 0U) {
if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) { if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
return true; return true;
} }
@ -277,20 +277,46 @@ bool can_lld_start(CANDriver *canp) {
/* Configuration can be performed now.*/ /* Configuration can be performed now.*/
canp->fdcan->CCCR |= FDCAN_CCCR_CCE; canp->fdcan->CCCR |= FDCAN_CCCR_CCE;
canp->fdcan->CCCR &= ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA);
/* Setting up operation mode except driver-controlled bits.*/ /* Setting up operation mode except driver-controlled bits.*/
canp->fdcan->NBTP = canp->config->NBTP;
canp->fdcan->DBTP = canp->config->DBTP; canp->fdcan->DBTP = canp->config->DBTP;
canp->fdcan->CCCR = canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA | canp->fdcan->CCCR |= canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA |
FDCAN_CCCR_CCE | FDCAN_CCCR_INIT); FDCAN_CCCR_CCE | FDCAN_CCCR_INIT);
canp->fdcan->TEST = canp->config->TEST; canp->fdcan->TEST = canp->config->TEST;
#ifdef STM32G4XX
canp->fdcan->RXGFC = canp->config->RXGFC;
#elif defined(STM32H7XX)
canp->fdcan->GFC = canp->config->RXGFC;
#else
#error "Unsupported STM32 for FDCAN LLD driver"
#endif
/* Enabling interrupts, only using interrupt zero.*/ /* Enabling interrupts, only using interrupt zero.*/
canp->fdcan->IR = (uint32_t)-1; canp->fdcan->IR = (uint32_t)-1;
canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE | canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE |
FDCAN_IE_RF0NE | FDCAN_IE_RF0LE | FDCAN_IE_RF0NE | FDCAN_IE_RF0LE |
FDCAN_IE_TCE; FDCAN_IE_TCE;
canp->fdcan->TXBTIE = FDCAN_TXBTIE_TIE;
canp->fdcan->ILE = FDCAN_ILE_EINT0; canp->fdcan->ILE = FDCAN_ILE_EINT0;
#ifdef STM32H7XX
/* H7 version of FDCAN has configurable memory layout, so configure it */
canp->fdcan->SIDFC = STM32_FDCAN_FLS_NBR << 16 | SRAMCAN_FLSSA;
canp->fdcan->XIDFC = STM32_FDCAN_FLE_NBR << 16 | SRAMCAN_FLESA;
canp->fdcan->RXF0C = STM32_FDCAN_RF0_NBR << 16 | SRAMCAN_RF0SA;
canp->fdcan->RXF1C = STM32_FDCAN_RF1_NBR << 16 | SRAMCAN_RF1SA;
canp->fdcan->RXBC = SRAMCAN_RBSA;
canp->fdcan->TXEFC = STM32_FDCAN_TEF_NBR << 16 | SRAMCAN_TEFSA;
/* NB: this doesn't set NDTB, but sets TFQS to run in queue mode with no dedicated buffers */
canp->fdcan->TXBC = STM32_FDCAN_TB_NBR << 24 | SRAMCAN_TBSA;
/* set to use the full 18-byte size buffer elements */
canp->fdcan->TXESC = 0x007;
canp->fdcan->RXESC = 0x777;
#endif /* STM32H7XX */
/* Going in active mode.*/ /* Going in active mode.*/
if (fdcan_active_mode(canp)) { if (fdcan_active_mode(canp)) {
osalDbgAssert(false, "CAN initialization failed, check clocks and pin config"); osalDbgAssert(false, "CAN initialization failed, check clocks and pin config");
@ -315,6 +341,7 @@ void can_lld_stop(CANDriver *canp) {
canp->fdcan->IE = 0U; canp->fdcan->IE = 0U;
canp->fdcan->IR = (uint32_t)-1; canp->fdcan->IR = (uint32_t)-1;
canp->fdcan->ILE = 0U; canp->fdcan->ILE = 0U;
canp->fdcan->TXBTIE = 0U;
/* Disables the peripheral.*/ /* Disables the peripheral.*/
(void) fdcan_clock_stop(canp); (void) fdcan_clock_stop(canp);
@ -371,22 +398,29 @@ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
* *
* @notapi * @notapi
*/ */
void can_lld_transmit(CANDriver *canp, void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) {
canmbx_t mailbox, uint32_t put_index;
const CANTxFrame *ctfp) {
uint32_t *tx_address; uint32_t *tx_address;
(void)mailbox; (void)mailbox;
osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES); osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES);
/* Retrieve the TX FIFO put index.*/
put_index = ((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);
/* Writing frame.*/ /* Writing frame.*/
tx_address = canp->ram_base + (SRAMCAN_TBSA / sizeof (uint32_t)); tx_address = canp->ram_base +
((SRAMCAN_TBSA + (put_index * SRAMCAN_TB_SIZE)) / sizeof (uint32_t));
*tx_address++ = ctfp->header32[0]; *tx_address++ = ctfp->header32[0];
*tx_address++ = ctfp->header32[1]; *tx_address++ = ctfp->header32[1];
for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) { for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) {
*tx_address++ = ctfp->data32[i / 4U]; *tx_address++ = ctfp->data32[i / 4U];
} }
/* Starting transmission.*/
canp->fdcan->TXBAR = ((uint32_t)1 << put_index);
} }
/** /**
@ -441,10 +475,18 @@ void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) {
} }
} }
/* GET index, add it and the length to the rx_address.*/ if (mailbox == 1U) {
/* GET index RXF0, add it and the length to the rx_address.*/
get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos; get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos;
rx_address = canp->ram_base + (SRAMCAN_RF0SA + rx_address = canp->ram_base + (SRAMCAN_RF0SA +
(get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t); (get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t);
}
else {
/* GET index RXF1, add it and the length to the rx_address.*/
get_index = (canp->fdcan->RXF1S & FDCAN_RXF1S_F1GI_Msk) >> FDCAN_RXF1S_F1GI_Pos;
rx_address = canp->ram_base + (SRAMCAN_RF1SA +
(get_index * SRAMCAN_RF1_SIZE)) / sizeof (uint32_t);
}
crfp->header32[0] = *rx_address++; crfp->header32[0] = *rx_address++;
crfp->header32[1] = *rx_address++; crfp->header32[1] = *rx_address++;
@ -548,7 +590,7 @@ void can_lld_serve_interrupt(CANDriver *canp) {
} }
/* Overflow events.*/ /* Overflow events.*/
if ((ir & FDCAN_IR_RF0N) != 0U) { if (((ir & FDCAN_IR_RF0L) != 0U) || ((ir & FDCAN_IR_RF1L) != 0U) ) {
_can_error_isr(canp, CAN_OVERFLOW_ERROR); _can_error_isr(canp, CAN_OVERFLOW_ERROR);
} }

View File

@ -181,14 +181,19 @@ typedef struct {
union { union {
struct { struct {
union { union {
struct {
uint32_t EID:29; /**< @brief Extended identifier. */ uint32_t EID:29; /**< @brief Extended identifier. */
} ext;
struct { struct {
uint32_t _R1:18; /**< @brief Reserved for offset. */ uint32_t _R1:18; /**< @brief Reserved for offset. */
uint32_t SID:11; /**< @brief Standard identifier. */ uint32_t SID:11; /**< @brief Standard identifier. */
} std;
struct {
uint32_t _R1:29; /**< @brief Reserved for offset. */
uint32_t RTR:1; /**< @brief Remote transmit request.*/ uint32_t RTR:1; /**< @brief Remote transmit request.*/
uint32_t XTD:1; /**< @brief Extended identifier. */ uint32_t XTD:1; /**< @brief Extended identifier. */
uint32_t ESI:1; /**< @brief Error state indicator. */ uint32_t ESI:1; /**< @brief Error state indicator. */
}; } common;
}; };
uint32_t _R2:16; uint32_t _R2:16;
uint32_t DLC:4; /**< @brief Data length code. */ uint32_t DLC:4; /**< @brief Data length code. */
@ -221,27 +226,34 @@ typedef struct {
/** /**
* @brief Frame header. * @brief Frame header.
*/ */
union {
struct { struct {
union { union {
uint32_t EID:29; /**< @brief Extended Identifier. */ struct {
uint32_t EID:29; /**< @brief Extended identifier. */
} ext;
struct { struct {
uint32_t _R1:18; uint32_t _R1:18;
uint32_t SID:11; /**< @brief Standard identifier. */ uint32_t SID:11; /**< @brief Standard identifier. */
} std;
struct {
uint32_t _R1:29; /**< @brief Reserved for offset. */
uint32_t RTR:1; /**< @brief Remote transmit request.*/ uint32_t RTR:1; /**< @brief Remote transmit request.*/
uint32_t XTD:1; /**< @brief Extended identifier. */ uint32_t XTD:1; /**< @brief Extended identifier. */
uint32_t ESI:1; /**< @brief Error state indicator. */ uint32_t ESI:1; /**< @brief Error state indicator. */
} common;
}; };
}; uint32_t RXTS:16; /**< @brief TX time stamp. */
uint16_t RXTS:16; /**< @brief TX time stamp. */ uint32_t DLC:4; /**< @brief Data length code. */
uint8_t DLC:4; /**< @brief Data length code. */ uint32_t BRS:1; /**< @brief Bit rate switch. */
uint8_t BRS:1; /**< @brief Bit rate switch. */ uint32_t FDF:1; /**< @brief FDCAN frame format. */
uint8_t FDF:1; /**< @brief FDCAN frame format. */ uint32_t _R2:2;
uint8_t _R2:2; uint32_t FIDX:7; /**< @brief Filter index. */
uint8_t FIDX:7; /**< @brief Filter index. */ uint32_t ANMF:1; /**< @brief Accepted non-matching
uint8_t ANMF:1; /**< @brief Accepted non-matching
frame. */ frame. */
}; };
uint32_t header32[2]; uint32_t header32[2];
};
/** /**
* @brief Frame data. * @brief Frame data.
*/ */
@ -304,6 +316,10 @@ typedef struct {
* @brief Driver configuration structure. * @brief Driver configuration structure.
*/ */
typedef struct { typedef struct {
/**
* @brief Nominal bit timing and prescaler register.
*/
uint32_t NBTP;
/** /**
* @brief Data bit timing and prescaler register. * @brief Data bit timing and prescaler register.
*/ */
@ -316,6 +332,10 @@ typedef struct {
* @brief Test configuration register. * @brief Test configuration register.
*/ */
uint32_t TEST; uint32_t TEST;
/**
* @brief Global filter configuration register.
*/
uint32_t RXGFC;
} CANConfig; } CANConfig;
/** /**

View File

@ -123,14 +123,14 @@
#define STM32_HAS_FDCAN1 TRUE #define STM32_HAS_FDCAN1 TRUE
#define STM32_HAS_FDCAN2 TRUE #define STM32_HAS_FDCAN2 TRUE
#define STM32_HAS_FDCAN3 FALSE #define STM32_HAS_FDCAN3 FALSE
#define STM32_FDCAN_FLS_NBR 128U #define STM32_FDCAN_FLS_NBR 64U
#define STM32_FDCAN_FLE_NBR 128U #define STM32_FDCAN_FLE_NBR 64U
#define STM32_FDCAN_RF0_NBR 64U #define STM32_FDCAN_RF0_NBR 56U
#define STM32_FDCAN_RF1_NBR 64U #define STM32_FDCAN_RF1_NBR 56U
#define STM32_FDCAN_RB_NBR 64U #define STM32_FDCAN_RB_NBR 0U
#define STM32_FDCAN_TEF_NBR 32U #define STM32_FDCAN_TEF_NBR 0U
#define STM32_FDCAN_TB_NBR 32U #define STM32_FDCAN_TB_NBR 32U
#define STM32_FDCAN_TM_NBR 64U #define STM32_FDCAN_TM_NBR 0U
/* DAC attributes.*/ /* DAC attributes.*/
#define STM32_HAS_DAC1_CH1 TRUE #define STM32_HAS_DAC1_CH1 TRUE