|
65 | 65 | // as (SRAMCAN_BASE + FDCAN_MESSAGE_RAM_SIZE - 0x4U) limits the usable number of words to 2559 words. |
66 | 66 | #define FDCAN_MESSAGE_RAM_SIZE (2560 - 1) |
67 | 67 |
|
| 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 | + |
68 | 74 | // also defined in <PROC>_hal_fdcan.c, but not able to declare extern and reach the variable |
69 | 75 | const uint8_t DLCtoBytes[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64}; |
70 | 76 |
|
@@ -461,4 +467,148 @@ void FDCAN2_IT1_IRQHandler(void) { |
461 | 467 | } |
462 | 468 | #endif |
463 | 469 |
|
| 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* |
464 | 614 | #endif // MICROPY_HW_ENABLE_CAN && MICROPY_HW_ENABLE_FDCAN |
0 commit comments