From b66145bd65843e25fe0faa7333d2841486ccfeed Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 5 Mar 2020 16:12:24 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13389 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c | 141 ++++++++++++++++++ os/hal/ports/STM32/STM32H7xx/stm32_registry.h | 8 + 2 files changed, 149 insertions(+) diff --git a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c index aa31c884a..a4a5ae0e4 100644 --- a/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c +++ b/os/hal/ports/STM32/LLD/FDCANv1/hal_can_lld.c @@ -30,6 +30,62 @@ /* Driver local definitions. */ /*===========================================================================*/ +/* Filter Standard Element Size in bytes.*/ +#define SRAMCAN_FLS_SIZE (1U * 4U) + +/* Filter Extended Element Size in bytes.*/ +#define SRAMCAN_FLE_SIZE (2U * 4U) + +/* RX FIFO 0 Elements Size in bytes.*/ +#define SRAMCAN_RF0_SIZE (18U * 4U) + +/* RX FIFO 1 Elements Size in bytes.*/ +#define SRAMCAN_RF1_SIZE (18U * 4U) + +/* RX Buffer Size in bytes.*/ +#define SRAMCAN_RB_SIZE (18U * 4U) + +/* TX Event FIFO Elements Size in bytes.*/ +#define SRAMCAN_TEF_SIZE (2U * 4U) + +/* TX FIFO/Queue Elements Size in bytes.*/ +#define SRAMCAN_TB_SIZE (18U * 4U) + +/* Filter List Standard Start Address.*/ +#define SRAMCAN_FLSSA ((uint32_t)0) + +/* Filter List Extended Start Address.*/ +#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + \ + (STM32_FDCAN_FLS_NBR * SRAMCAN_FLS_SIZE))) + +/* RX FIFO 0 Start Address.*/ +#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + \ + (STM32_FDCAN_FLE_NBR * SRAMCAN_FLE_SIZE))) + +/* RX FIFO 1 Start Address.*/ +#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + \ + (STM32_FDCAN_RF0_NBR * SRAMCAN_RF0_SIZE))) + +/* RX Buffer Start Address.*/ +#define SRAMCAN_RBSA ((uint32_t)(SRAMCAN_RF1SA + \ + (STM32_FDCAN_RF1_NBR * SRAMCAN_RF1_SIZE))) + +/* TX Event FIFO Start Address.*/ +#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RBSA + \ + (STM32_FDCAN_TEF_NBR * SRAMCAN_RB_SIZE))) + +/* TX Buffers Start Address.*/ +#define SRAMCAN_TBSA ((uint32_t)(SRAMCAN_TEFSA + \ + (STM32_FDCAN_TEF_NBR * SRAMCAN_TEF_SIZE))) + +#define SRAMCAN_TMSA ((uint32_t)(SRAMCAN_TBSA + \ + (STM32_FDCAN_TB_NBR * SRAMCAN_TB_SIZE))) + +/* Message RAM size.*/ +#define SRAMCAN_SIZE ((uint32_t)(SRAMCAN_TMSA + \ + (STM32_FDCAN_TM_NBR * SRAMCAN_TM_SIZE))) + + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -48,6 +104,11 @@ CANDriver CAND2; /* Driver local variables and types. */ /*===========================================================================*/ +static const uint8_t dlc_to_bytes[] = { + 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, + 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U +}; + /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ @@ -142,6 +203,9 @@ void can_lld_stop(CANDriver *canp) { */ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { + (void)mailbox; + + return (bool)((canp->fdcan->TXFQS & FDCAN_TXFQS_TFQF) == 0U); } /** @@ -156,7 +220,19 @@ bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) { void can_lld_transmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) { + uint32_t *tx_address; + (void)mailbox; + + osalDbgCheck(dlc_to_bytes[ctfp->DLC] <= CAN_MAX_DLC_BYTES); + + /* Writing frame.*/ + tx_address = canp->ram_base + (SRAMCAN_TBSA / 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]; + } } /** @@ -173,6 +249,17 @@ void can_lld_transmit(CANDriver *canp, */ bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { + switch (mailbox) { + case CAN_ANY_MAILBOX: + return can_lld_is_rx_nonempty(canp, 1U) || + can_lld_is_rx_nonempty(canp, 2U); + case 1: + return (bool)((canp->fdcan->RXF0S & FDCAN_RXF0S_F0FL) != 0U); + case 2: + return (bool)((canp->fdcan->RXF1S & FDCAN_RXF1S_F1FL) != 0U); + default: + return false; + } } /** @@ -185,7 +272,59 @@ bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) { * @notapi */ void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) { + uint32_t get_index; + uint32_t *rx_address; + if (mailbox == CAN_ANY_MAILBOX) { + if (can_lld_is_rx_nonempty(canp, 1U)) { + mailbox = 1U; + } + else if (can_lld_is_rx_nonempty(canp, 2U)) { + mailbox = 2U; + } + else { + 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); + crfp->header32[0] = *rx_address++; + crfp->header32[1] = *rx_address++; + + /* Copy message from FDCAN peripheral's SRAM to structure. RAM is restricted + to word aligned accesses, so up to 3 extra bytes may be copied.*/ + for (unsigned i = 0U; i < dlc_to_bytes[crfp->DLC]; i += 4U) { + crfp->data32[i / 4U] = *rx_address++; + } + + /* Acknowledge receipt by writing the get-index to the acknowledge + register RXFxA then re-enable RX FIFO message arrived interrupt once + the FIFO is emptied.*/ + if (mailbox == 1U) { + uint32_t rxf0a = canp->fdcan->RXF0A; + rxf0a &= ~FDCAN_RXF0A_F0AI_Msk; + rxf0a |= get_index << FDCAN_RXF0A_F0AI_Pos; + canp->fdcan->RXF0A = rxf0a; + + if (!can_lld_is_rx_nonempty(canp, mailbox)) { +// canp->fdcan->IR = FDCAN_IR_RF0N; + canp->fdcan->IE |= FDCAN_IE_RF0NE; + } + } + else { + uint32_t rxf1a = canp->fdcan->RXF1A; + rxf1a &= ~FDCAN_RXF1A_F1AI_Msk; + rxf1a |= get_index << FDCAN_RXF1A_F1AI_Pos; + canp->fdcan->RXF1A = rxf1a; + + if (!can_lld_is_rx_nonempty(canp, mailbox)) { +// canp->fdcan->IR = FDCAN_IR_RF1N; + canp->fdcan->IE |= FDCAN_IE_RF1NE; + } + } } /** @@ -198,6 +337,8 @@ void can_lld_receive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) { */ void can_lld_abort(CANDriver *canp, canmbx_t mailbox) { + (void)canp; + (void)mailbox; } #if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) diff --git a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h index 02b283d40..341fc4201 100644 --- a/os/hal/ports/STM32/STM32H7xx/stm32_registry.h +++ b/os/hal/ports/STM32/STM32H7xx/stm32_registry.h @@ -68,6 +68,14 @@ /* CAN attributes.*/ #define STM32_HAS_FDCAN1 TRUE #define STM32_HAS_FDCAN2 TRUE +#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_TB_NBR 32U +#define STM32_FDCAN_TM_NBR 64U /* DAC attributes.*/ #define STM32_HAS_DAC1_CH1 TRUE