forked from dronecan/libcanard
-
Notifications
You must be signed in to change notification settings - Fork 1
Flytrex STM32G4 driver #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
5e217cc
Initial draft, not yet tested
grisharevzin 0d2bc4d
Doc updates
grisharevzin eac645b
Import fixes
grisharevzin 560ab4d
Minor WIP changes
grisharevzin 5a78e09
Compiler warnings
grisharevzin c3a21cb
aligned #ifdef -> #if CANARD_ENABLE_CANFD
grisharevzin af119d1
WIP: hardware works (messages are sent/received), cleaning code
grisharevzin 2198a83
Debug & cleanup; filters, transmission, reception are working
grisharevzin a9d701a
Fixed put_index calculation in transmit()
grisharevzin e82eb76
silenced unused parameter warning for non-FD mode
grisharevzin 4c1c14a
Fixed acknowledging received frames
grisharevzin f08f41c
tabs -> spaces
grisharevzin 989e47e
Added canard_stm32g4fdcan_get_statistics()
grisharevzin 79a9934
Merge branch 'master' into add-stm32g4-fdcan-driver
grisharevzin 35c70b1
Fixed FD frame reception
grisharevzin 2982c7b
Set TDC = 0 for BRS
grisharevzin 71c5040
Added wipe_filters()
grisharevzin c3f7fd5
Fixed enable_automatic_retransmission
grisharevzin cebebe5
CR, minor
grisharevzin 748b9f1
Fixed incorrect ECR values
grisharevzin e1aeadb
Fixed incorrect IP offset calculation
grisharevzin c3a502c
CR, license notes
grisharevzin 6c86ab1
CR, minor
grisharevzin 2d48474
extern 'C'
grisharevzin 2e696cb
CR, minor
grisharevzin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # STM32G4 FDCAN driver for libcanard/DroneCAN | ||
|
|
||
| This is a bare-bones driver for the variety of FDCAN that's found in STM32G4 series. | ||
|
|
||
| * TX FIFO is used in queue mode | ||
| * Incoming messages are prioritized based on filters (see below). | ||
| * Multiple instances are supported | ||
| * No dependencies, no interrupts (unless you want them) | ||
| * Specific for DroneCAN. | ||
|
|
||
| FDCANs are slightly different between STM32G4, STM32H7 (this has a very configurable SRAM) and STM32G0. | ||
| So this is only for G4, but can probably be extended to support everything. | ||
|
|
||
| ## General usage | ||
|
|
||
| ### Initialization | ||
|
|
||
| 1. Store a `canard_stm32g4_fdcan_driver` somewhere and set the `fdcan` pointer | ||
| to one of `FDCAN1_ADDR`/`FDCAN2_ADDR`/`FDCAN3_ADDR`, then | ||
| call `canard_stm32g4fdcan_init`. | ||
|
|
||
| 2. Then configure filters by calling `canard_stm32g4fdcan_type_id_filter` as many times as needed (8 double | ||
| rules can be created all in all). | ||
|
|
||
| 3. Call `canard_stm32g4fdcan_start`. | ||
|
|
||
| 4. After a Node ID has been assigned (or if you know it beforehand), call `canard_stm32g4fdcan_enable_automatic_retransmission`. | ||
|
|
||
| It's the user's responsibility to provide clock to the chosen FDCAN peripheral and configure I/O pins. | ||
|
|
||
| ### Reception | ||
|
|
||
| The driver sets up two RX FIFOs, FIFO0 for "more important" and FIFO1 for "less important" messages. | ||
|
|
||
| Three things can happen to a message on reception (see `canard_stm32g4fdcan_type_id_filter`): | ||
| 1. The DroneCAN data type ID is in the "accept" filter (`accept_not_reject=1`) -> goes to FIFO0 | ||
| 2. The DroneCAN data type ID is in the "reject" filter (`accept_not_reject=0`) -> discarded | ||
| 3. The DroneCAN data type ID is in neither -> goes to FIFO1 | ||
|
|
||
| `canard_stm32g4fdcan_receive` reads one message at a time and prefers FIFO0. | ||
|
|
||
| For instance, a ESC | ||
| 1. would prioritize `1031.RawCommand` above anything else - so this ID should be accepted. | ||
| 2. would reject spammy `1034.Status` messages from other ESCs - so this ID should be rejected. | ||
|
|
||
| The filter functions are used by DroneCAN data type IDs, not CAN frame IDs. | ||
|
|
||
| Note that all service requests will automatically go to FIFO1. | ||
|
|
||
| ## Config | ||
|
|
||
| If `CANARD_ENABLE_CANFD` is defined, FDCAN will be configured in long frame mode + bitrate switch mode. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| /* | ||
| * Copyright (c) 2024-2026 Flytrex, by Grisha Revzin | ||
| * | ||
| * Distributed under the MIT License, available in the file LICENSE. | ||
| * | ||
| * Created on: Sep 10, 2024 | ||
| */ | ||
|
|
||
| #ifndef INTERNAL_FDCAN_H | ||
| #define INTERNAL_FDCAN_H | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| /* ------------------- SRAM layout --------------------------------------------------------------------------------- */ | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| volatile uint32_t CREL; | ||
| volatile uint32_t ENDN; | ||
| volatile uint32_t RESERVED1; | ||
| volatile uint32_t DBTP; | ||
| volatile uint32_t TEST; | ||
| volatile uint32_t RWD; | ||
| volatile uint32_t CCCR; | ||
| volatile uint32_t NBTP; | ||
| volatile uint32_t TSCC; | ||
| volatile uint32_t TSCV; | ||
| volatile uint32_t TOCC; | ||
| volatile uint32_t TOCV; | ||
| volatile uint32_t RESERVED2[4]; | ||
| volatile uint32_t ECR; | ||
| volatile uint32_t PSR; | ||
| volatile uint32_t TDCR; | ||
| volatile uint32_t RESERVED3; | ||
| volatile uint32_t IR; | ||
| volatile uint32_t IE; | ||
| volatile uint32_t ILS; | ||
| volatile uint32_t ILE; | ||
| volatile uint32_t RESERVED4[8]; | ||
| volatile uint32_t RXGFC; | ||
| volatile uint32_t XIDAM; | ||
| volatile uint32_t HPMS; | ||
| volatile uint32_t RESERVED5; | ||
| volatile uint32_t RXF0S; | ||
| volatile uint32_t RXF0A; | ||
| volatile uint32_t RXF1S; | ||
| volatile uint32_t RXF1A; | ||
| volatile uint32_t RESERVED6[8]; | ||
| volatile uint32_t TXBC; | ||
| volatile uint32_t TXFQS; | ||
| volatile uint32_t TXBRP; | ||
| volatile uint32_t TXBAR; | ||
| volatile uint32_t TXBCR; | ||
| volatile uint32_t TXBTO; | ||
| volatile uint32_t TXBCF; | ||
| volatile uint32_t TXBTIE; | ||
| volatile uint32_t TXBCIE; | ||
| volatile uint32_t TXEFS; | ||
| volatile uint32_t TXEFA; | ||
| } fdcan_registers; | ||
|
|
||
| /* Helper to iterate over RXFxS/A */ | ||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| volatile uint32_t RXFxS; | ||
| volatile uint32_t RXFxA; | ||
| } fdcan_rxfifo_regs; | ||
|
|
||
| /* ------------------- SRAM layout --------------------------------------------------------------------------------- */ | ||
| /* Note: bitfields only to get a register-like view in GDB. Don't use them directly, it explodes. */ | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| union { | ||
| uint32_t t0; | ||
| struct { | ||
| uint32_t id : 29; | ||
| uint32_t rtr : 1; /* remote frame */ | ||
| uint32_t xtd : 1; /* extended frame */ | ||
| uint32_t esi : 1; /* Force error passive flag */ | ||
| }; | ||
| }; | ||
|
|
||
| union { | ||
| uint32_t t1; | ||
| struct { | ||
| uint32_t reserved0 : 16; | ||
| uint32_t dlc : 4; /* DLC */ | ||
| uint32_t brs : 1; /* Bit Rate Switching Frame */ | ||
| uint32_t fdf : 1; /* CAN FD frame */ | ||
| uint32_t reserved1 : 1; | ||
| uint32_t efc : 1; /* store tx events */ | ||
| uint32_t mm : 8; /* message marker (tx events) */ | ||
| }; | ||
| }; | ||
| uint32_t data[64 / sizeof(uint32_t)]; | ||
| } fdcan_tx_buf_element; | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| union { | ||
| uint32_t r0; | ||
| struct { | ||
| uint32_t id : 29; | ||
| uint32_t rtr : 1; /* remote */ | ||
| uint32_t xtd : 1; /* extended */ | ||
| uint32_t esi : 1; /* transmitter error passive */ | ||
| }; | ||
| }; | ||
|
|
||
| union { | ||
| uint32_t r1; | ||
| struct { | ||
| uint32_t rxts : 16;/* timestamp */ | ||
| uint32_t dlc : 4; | ||
| uint32_t brs : 1; /* Bit Rate Switching Frame */ | ||
| uint32_t fdf : 1; /* CAN FD frame */ | ||
| uint32_t reserved0 : 1; | ||
| uint32_t fidx : 7; /* filter index */ | ||
| uint32_t anmf : 1; /* no filter matched */ | ||
| }; | ||
| }; | ||
| uint32_t data[64 / sizeof(uint32_t)]; | ||
| } fdcan_rx_buf_element; | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| /* not detailed, standard IDs not used for DroneCAN */ | ||
| uint32_t stub; | ||
| } fdcan_stdid_filter_element; | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| /* not detailed, tx events are not used */ | ||
| uint32_t stub[2]; | ||
| } fdcan_tx_event_element; | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| union { | ||
| uint32_t f0; | ||
| struct { | ||
| uint32_t efid1 : 29; | ||
| enum { | ||
| FILT_ELEM_EFEC_DISABLE, | ||
| FILT_ELEM_EFEC_STORE_RXFIFO0, | ||
| FILT_ELEM_EFEC_STORE_RXFIFO1, | ||
| FILT_ELEM_EFEC_REJECT, | ||
| FILT_ELEM_EFEC_SET_PRIORITY_STORE_RXFIFO0, | ||
| FILT_ELEM_EFEC_SET_PRIORITY_STORE_RXFIFO1, | ||
| FILT_ELEM_EFEC_RESERVED, | ||
| } efec : 3; | ||
| }; | ||
| }; | ||
| union { | ||
| uint32_t f1; | ||
| struct { | ||
| uint32_t efid2 : 29; | ||
| uint32_t reserved0 : 1; | ||
| enum { | ||
| FILT_ELEM_EFT_RANGE, | ||
| FILT_ELEM_EFT_DUAL_ID, | ||
| FILT_ELEM_EFT_ID_MASK, | ||
| FILT_ELEM_EFT_RANGE_NO_XIDAM | ||
| } eft : 2; | ||
| }; | ||
| }; | ||
| } fdcan_extid_filter_element; | ||
|
|
||
| /* Figure 669 RM0440 */ | ||
| #define FDCAN_NUM_STDID_FE 28 | ||
| #define FDCAN_NUM_EXTID_FE 8 | ||
| #define FDCAN_NUM_RXFIFO_ELEMENTS 3 | ||
| #define FDCAN_NUM_TX_EVENT_FIFOS 3 | ||
| #define FDCAN_NUM_TX_BUF 3 | ||
|
|
||
| typedef struct __attribute__((packed, aligned(4))) { | ||
| fdcan_stdid_filter_element stdid_filter_element[FDCAN_NUM_STDID_FE]; // 28 // 28 | ||
| fdcan_extid_filter_element extid_filter_element[FDCAN_NUM_EXTID_FE]; // 16 // 44 | ||
| fdcan_rx_buf_element rxfifo0[FDCAN_NUM_RXFIFO_ELEMENTS]; // 54 // 98 | ||
| fdcan_rx_buf_element rxfifo1[FDCAN_NUM_RXFIFO_ELEMENTS]; // 54 // 152 | ||
| fdcan_tx_event_element txevent_fifo[FDCAN_NUM_TX_EVENT_FIFOS]; // 6 // 158 | ||
| fdcan_tx_buf_element txbuf[FDCAN_NUM_TX_BUF]; // 54 // 212 == 0x350 | ||
| } fdcan_sram; | ||
|
|
||
| _Static_assert(sizeof(fdcan_sram) == 0x350, "fdcan_sram size must be 0x350"); | ||
|
|
||
| #define FDCAN1 ((fdcan_registers *) FDCAN1_ADDR) | ||
| #define FDCAN2 ((fdcan_registers *) FDCAN2_ADDR) | ||
| #define FDCAN3 ((fdcan_registers *) FDCAN3_ADDR) | ||
|
|
||
| #define IP_OFFSET (FDCAN2_ADDR - FDCAN1_ADDR) | ||
|
|
||
| #define SRAMCAN_START 0x4000A400U | ||
grisharevzin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
grisharevzin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #endif | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.