Skip to content

Commit 6f835b3

Browse files
committed
stm32: Implement index-aware STM32G4 FDCAN HAL TX functions.
These are oddly missing from the STM32G4 HAL, but the reference manual describes being able to use them and the implementations seem to work as expected. Note that unlike STM32H7 it doesn't seem like we must use this approach, because HAL_FDCAN_AddMessageToTxFifoQ() does seem to not have the issues with priority inversion seen on the H7. However it's simpler to use the same API for both... Signed-off-by: Angus Gratton <angus@redyak.com.au> Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 0225704 commit 6f835b3

1 file changed

Lines changed: 150 additions & 0 deletions

File tree

ports/stm32/fdcan.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@
6565
// as (SRAMCAN_BASE + FDCAN_MESSAGE_RAM_SIZE - 0x4U) limits the usable number of words to 2559 words.
6666
#define FDCAN_MESSAGE_RAM_SIZE (2560 - 1)
6767

68+
#if defined(STM32G4)
69+
// These HAL APIs are not implemented for STM32G4, so we implement them here...
70+
static HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxBuffer(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex);
71+
static HAL_StatusTypeDef HAL_FDCAN_EnableTxBufferRequest(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndex);
72+
#endif // STM32G4
73+
6874
// also defined in <PROC>_hal_fdcan.c, but not able to declare extern and reach the variable
6975
const uint8_t DLCtoBytes[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
7076

@@ -461,4 +467,148 @@ void FDCAN2_IT1_IRQHandler(void) {
461467
}
462468
#endif
463469

470+
#if defined(STM32G4)
471+
// These implementations are copied from stm32h7xx_hal_fdcan.c with modifications for different G4 registers & code formatting
472+
473+
// *FORMAT-OFF*
474+
// ^^^ Keep original STM HAL code style for easier comparison
475+
476+
static void FDCAN_CopyMessageToRAM(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex);
477+
478+
static HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxBuffer(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData, uint32_t BufferIndex)
479+
{
480+
HAL_FDCAN_StateTypeDef state = hfdcan->State;
481+
482+
/* Check function parameters */
483+
assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
484+
if (pTxHeader->IdType == FDCAN_STANDARD_ID)
485+
{
486+
assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
487+
}
488+
else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
489+
{
490+
assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
491+
}
492+
assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
493+
assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
494+
assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
495+
assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
496+
assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
497+
assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
498+
assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));
499+
assert_param(IS_FDCAN_TX_LOCATION(BufferIndex));
500+
501+
if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
502+
{
503+
/* Check that the selected buffer has an allocated area into the RAM */
504+
if (POSITION_VAL(BufferIndex) >= CAN_TX_QUEUE_LEN) // Note: Modified for G4 here
505+
{
506+
/* Update error code */
507+
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
508+
509+
return HAL_ERROR;
510+
}
511+
512+
/* Check that there is no transmission request pending for the selected buffer */
513+
if ((hfdcan->Instance->TXBRP & BufferIndex) != 0U)
514+
{
515+
/* Update error code */
516+
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PENDING;
517+
518+
return HAL_ERROR;
519+
}
520+
else
521+
{
522+
/* Add the message to the Tx buffer */
523+
FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, POSITION_VAL(BufferIndex));
524+
}
525+
526+
/* Return function status */
527+
return HAL_OK;
528+
}
529+
else
530+
{
531+
/* Update error code */
532+
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
533+
534+
return HAL_ERROR;
535+
}
536+
}
537+
538+
static HAL_StatusTypeDef HAL_FDCAN_EnableTxBufferRequest(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndex)
539+
{
540+
if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
541+
{
542+
/* Add transmission request */
543+
hfdcan->Instance->TXBAR = BufferIndex;
544+
545+
/* Return function status */
546+
return HAL_OK;
547+
}
548+
else
549+
{
550+
/* Update error code */
551+
hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
552+
553+
return HAL_ERROR;
554+
}
555+
}
556+
557+
#define SRAMCAN_TFQ_SIZE (18U * 4U) /* TX FIFO/Queue Elements Size in bytes */
558+
559+
// This function is copied 100% as-is from stm32g4xx_hal_fdcan.c, unfortunately
560+
static void FDCAN_CopyMessageToRAM(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData,
561+
uint32_t BufferIndex)
562+
{
563+
uint32_t TxElementW1;
564+
uint32_t TxElementW2;
565+
uint32_t *TxAddress;
566+
uint32_t ByteCounter;
567+
568+
/* Build first word of Tx header element */
569+
if (pTxHeader->IdType == FDCAN_STANDARD_ID)
570+
{
571+
TxElementW1 = (pTxHeader->ErrorStateIndicator |
572+
FDCAN_STANDARD_ID |
573+
pTxHeader->TxFrameType |
574+
(pTxHeader->Identifier << 18U));
575+
}
576+
else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
577+
{
578+
TxElementW1 = (pTxHeader->ErrorStateIndicator |
579+
FDCAN_EXTENDED_ID |
580+
pTxHeader->TxFrameType |
581+
pTxHeader->Identifier);
582+
}
583+
584+
/* Build second word of Tx header element */
585+
TxElementW2 = ((pTxHeader->MessageMarker << 24U) |
586+
pTxHeader->TxEventFifoControl |
587+
pTxHeader->FDFormat |
588+
pTxHeader->BitRateSwitch |
589+
pTxHeader->DataLength);
590+
591+
/* Calculate Tx element address */
592+
TxAddress = (uint32_t *)(hfdcan->msgRam.TxFIFOQSA + (BufferIndex * SRAMCAN_TFQ_SIZE));
593+
594+
/* Write Tx element header to the message RAM */
595+
*TxAddress = TxElementW1;
596+
TxAddress++;
597+
*TxAddress = TxElementW2;
598+
TxAddress++;
599+
600+
/* Write Tx payload to the message RAM */
601+
for (ByteCounter = 0; ByteCounter < DLCtoBytes[pTxHeader->DataLength >> 16U]; ByteCounter += 4U)
602+
{
603+
*TxAddress = (((uint32_t)pTxData[ByteCounter + 3U] << 24U) |
604+
((uint32_t)pTxData[ByteCounter + 2U] << 16U) |
605+
((uint32_t)pTxData[ByteCounter + 1U] << 8U) |
606+
(uint32_t)pTxData[ByteCounter]);
607+
TxAddress++;
608+
}
609+
}
610+
611+
#endif // STM32G4
612+
613+
// *FORMAT-ON*
464614
#endif // MICROPY_HW_ENABLE_CAN && MICROPY_HW_ENABLE_FDCAN

0 commit comments

Comments
 (0)