Skip to content

Commit

Permalink
Merge pull request #12 from mck1117/canfd-fix
Browse files Browse the repository at this point in the history
backport and fix FDCAN driver
  • Loading branch information
rusefillc committed Mar 9, 2021
2 parents 6b0f623 + cd5bb10 commit 948b015
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 51 deletions.
90 changes: 66 additions & 24 deletions os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static bool fdcan_clock_stop(CANDriver *canp) {
canp->fdcan->CCCR |= FDCAN_CCCR_CSR;
start = osalOsGetSystemTimeX();
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)) {
return true;
}
Expand Down Expand Up @@ -202,21 +202,21 @@ void can_lld_init(void) {
/* Driver initialization.*/
canObjectInit(&CAND1);
CAND1.fdcan = FDCAN1;
CAND1.ram_base = (uint32_t *) (SRAMCAN_BASE + 0U * SRAMCAN_SIZE);
CAND1.ram_base = (uint32_t *)(SRAMCAN_BASE + 0U * SRAMCAN_SIZE);
#endif

#if STM32_CAN_USE_FDCAN2
/* Driver initialization.*/
canObjectInit(&CAND2);
CAND2.fdcan = FDCAN2;
CAND2.ram_base = (uint32_t *) (SRAMCAN_BASE + 1U * SRAMCAN_SIZE);
CAND2.ram_base = (uint32_t *)(SRAMCAN_BASE + 1U * SRAMCAN_SIZE);
#endif

#if STM32_CAN_USE_FDCAN3
/* Driver initialization.*/
canObjectInit(&CAND3);
CAND3.fdcan = FDCAN3;
CAND3.ram_base = (uint32_t *) (SRAMCAN_BASE + 2U * SRAMCAN_SIZE);
CAND3.ram_base = (uint32_t *)(SRAMCAN_BASE + 2U * SRAMCAN_SIZE);
#endif
}

Expand Down Expand Up @@ -276,20 +276,46 @@ bool can_lld_start(CANDriver *canp) {
}

/* 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.*/
canp->fdcan->DBTP = canp->config->DBTP;
canp->fdcan->CCCR = canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA |
FDCAN_CCCR_CCE | FDCAN_CCCR_INIT);
canp->fdcan->TEST = canp->config->TEST;
canp->fdcan->NBTP = canp->config->NBTP;
canp->fdcan->DBTP = canp->config->DBTP;
canp->fdcan->CCCR |= canp->config->CCCR & ~(FDCAN_CCCR_CSR | FDCAN_CCCR_CSA |
FDCAN_CCCR_CCE | FDCAN_CCCR_INIT);
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.*/
canp->fdcan->IR = (uint32_t)-1;
canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE |
FDCAN_IE_RF0NE | FDCAN_IE_RF0LE |
FDCAN_IE_TCE;
canp->fdcan->ILE = FDCAN_ILE_EINT0;
canp->fdcan->IR = (uint32_t)-1;
canp->fdcan->IE = FDCAN_IE_RF1NE | FDCAN_IE_RF1LE |
FDCAN_IE_RF0NE | FDCAN_IE_RF0LE |
FDCAN_IE_TCE;
canp->fdcan->TXBTIE = FDCAN_TXBTIE_TIE;
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.*/
if (fdcan_active_mode(canp)) {
Expand All @@ -315,6 +341,7 @@ void can_lld_stop(CANDriver *canp) {
canp->fdcan->IE = 0U;
canp->fdcan->IR = (uint32_t)-1;
canp->fdcan->ILE = 0U;
canp->fdcan->TXBTIE = 0U;

/* Disables the peripheral.*/
(void) fdcan_clock_stop(canp);
Expand Down Expand Up @@ -371,22 +398,29 @@ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
*
* @notapi
*/
void can_lld_transmit(CANDriver *canp,
canmbx_t mailbox,
const CANTxFrame *ctfp) {
void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) {
uint32_t put_index;
uint32_t *tx_address;

(void)mailbox;

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.*/
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[1];
for (unsigned i = 0U; i < dlc_to_bytes[ctfp->DLC]; i += 4U) {
*tx_address++ = ctfp->data32[i / 4U];
}

/* Starting transmission.*/
canp->fdcan->TXBAR = ((uint32_t)1 << put_index);
}

/**
Expand Down Expand Up @@ -440,11 +474,19 @@ void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) {
return;
}
}

/* GET index, add it and the length to the rx_address.*/
get_index = (canp->fdcan->RXF0S & FDCAN_RXF0S_F0GI_Msk) >> FDCAN_RXF0S_F0GI_Pos;
rx_address = canp->ram_base + (SRAMCAN_RF0SA +
(get_index * SRAMCAN_RF0_SIZE)) / sizeof (uint32_t);

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;
rx_address = canp->ram_base + (SRAMCAN_RF0SA +
(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[1] = *rx_address++;

Expand Down Expand Up @@ -548,7 +590,7 @@ void can_lld_serve_interrupt(CANDriver *canp) {
}

/* 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);
}

Expand Down
60 changes: 40 additions & 20 deletions os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,19 @@ typedef struct {
union {
struct {
union {
uint32_t EID:29; /**< @brief Extended identifier. */
struct {
uint32_t EID:29; /**< @brief Extended identifier. */
} ext;
struct {
uint32_t _R1:18; /**< @brief Reserved for offset. */
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 XTD:1; /**< @brief Extended identifier. */
uint32_t ESI:1; /**< @brief Error state indicator. */
};
} common;
};
uint32_t _R2:16;
uint32_t DLC:4; /**< @brief Data length code. */
Expand Down Expand Up @@ -221,27 +226,34 @@ typedef struct {
/**
* @brief Frame header.
*/
struct {
union {
uint32_t EID:29; /**< @brief Extended Identifier. */
struct {
uint32_t _R1:18;
uint32_t SID:11; /**< @brief Standard identifier. */
uint32_t RTR:1; /**< @brief Remote transmit request.*/
uint32_t XTD:1; /**< @brief Extended identifier. */
uint32_t ESI:1; /**< @brief Error state indicator. */
union {
struct {
union {
struct {
uint32_t EID:29; /**< @brief Extended identifier. */
} ext;
struct {
uint32_t _R1:18;
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 XTD:1; /**< @brief Extended identifier. */
uint32_t ESI:1; /**< @brief Error state indicator. */
} common;
};
};
uint16_t RXTS:16; /**< @brief TX time stamp. */
uint8_t DLC:4; /**< @brief Data length code. */
uint8_t BRS:1; /**< @brief Bit rate switch. */
uint8_t FDF:1; /**< @brief FDCAN frame format. */
uint8_t _R2:2;
uint8_t FIDX:7; /**< @brief Filter index. */
uint8_t ANMF:1; /**< @brief Accepted non-matching
uint32_t RXTS:16; /**< @brief TX time stamp. */
uint32_t DLC:4; /**< @brief Data length code. */
uint32_t BRS:1; /**< @brief Bit rate switch. */
uint32_t FDF:1; /**< @brief FDCAN frame format. */
uint32_t _R2:2;
uint32_t FIDX:7; /**< @brief Filter index. */
uint32_t ANMF:1; /**< @brief Accepted non-matching
frame. */
};
uint32_t header32[2];
};
uint32_t header32[2];
/**
* @brief Frame data.
*/
Expand Down Expand Up @@ -304,6 +316,10 @@ typedef struct {
* @brief Driver configuration structure.
*/
typedef struct {
/**
* @brief Nominal bit timing and prescaler register.
*/
uint32_t NBTP;
/**
* @brief Data bit timing and prescaler register.
*/
Expand All @@ -316,6 +332,10 @@ typedef struct {
* @brief Test configuration register.
*/
uint32_t TEST;
/**
* @brief Global filter configuration register.
*/
uint32_t RXGFC;
} CANConfig;

/**
Expand Down
14 changes: 7 additions & 7 deletions os/hal/ports/STM32/STM32H7xx/stm32_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@
#define STM32_HAS_FDCAN1 TRUE
#define STM32_HAS_FDCAN2 TRUE
#define STM32_HAS_FDCAN3 FALSE
#define STM32_FDCAN_FLS_NBR 128U
#define STM32_FDCAN_FLE_NBR 128U
#define STM32_FDCAN_RF0_NBR 64U
#define STM32_FDCAN_RF1_NBR 64U
#define STM32_FDCAN_RB_NBR 64U
#define STM32_FDCAN_TEF_NBR 32U
#define STM32_FDCAN_FLS_NBR 64U
#define STM32_FDCAN_FLE_NBR 64U
#define STM32_FDCAN_RF0_NBR 56U
#define STM32_FDCAN_RF1_NBR 56U
#define STM32_FDCAN_RB_NBR 0U
#define STM32_FDCAN_TEF_NBR 0U
#define STM32_FDCAN_TB_NBR 32U
#define STM32_FDCAN_TM_NBR 64U
#define STM32_FDCAN_TM_NBR 0U

/* DAC attributes.*/
#define STM32_HAS_DAC1_CH1 TRUE
Expand Down

0 comments on commit 948b015

Please sign in to comment.