Until now, STM32 MCUs classic CAN support is coded in can.c file.
However CAN FD in STM32G4 family is designed in a very different way:
* CAN FD channels are independant
* CAN FD channel configuration is done in a dedicated RAM block called
message RAM, with one message RAM per channel
* Each message RAM is divided this way:
- 11-bit filter (28 elements / 28 words)
- 29-bit filter (8 elements / 16 words)
- Rx FIFO 0 (3 elements / 54 words)
- Rx FIFO 1 (3 elements / 54 words)
- Tx event FIFO (3 elements / 6 words)
- Tx buffers (3 elements / 54 words)
Due to these design differences with other STM32 MCUs, the choice is
made to split the driver in two files:
* classiccan.c for STM32 MCUs that support classical CAN. This file
has just been renamed (previously can.c) to avoid build conflicts
but does not introduce changes
* fdcan.c for STM32 MCUs that support CAN FD
Message RAM definitions is not provided in CMSIS headers of the STM32G4
family, they are defined in fdcandev_stm32.h. Those definitions could be
extracted to a new file for each STM32 families as some differences
exist with other STM32 families that support CAN FD (for instance
STM32H7). This could be done in a futher commit, according to new
families requirements.
CAN hardware parameters stay similar and are kept in can_params.h.
There are 36 filters per channel:
* 28 first filters are standard ID (11 bit) filters
* 8 last filters are extended ID (29 bit) filters
On each Tx frame sent, the STM32G4 can store Tx events in a dedicated
FIFO. This feature is not yet implemented and Tx event FIFO is disabled
by default.
Automatic retransmission on arbitration loss is enabled by default by
the STM32G4.
About Rx, if no filter is configured, all frames are accepted by
default.
Signed-off-by: Gilles DOFFE <gilles.doffe@rtone.fr>
RIOT implementation of CAN bus relies on SocketCAN model.
Since commit c398e56 (can: add optional DLC element to Classical CAN
frame structure), '__u8 can_dlc' attribute of struct can_frame is
considered as deprecated in SocketCAN and kept for legacy support.
Attribute '__u8 len' should be used instead.
union {
/* CAN frame payload length in byte (0 .. CAN_MAX_DLEN)
* was previously named can_dlc so we need to carry that
* name for legacy support
*/
__u8 len;
__u8 can_dlc; /* deprecated */
};
Moreover, CAN FD frame structure does not support legacy attribute
'can_dlc', making 'len' mandatory for incoming CAN FD support in RIOT.
struct canfd_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 len; /* frame payload length in byte */
__u8 flags; /* additional flags for CAN FD */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[CANFD_MAX_DLEN]
__attribute__((aligned(8)));
};
Signed-off-by: Gilles DOFFE <gilles.doffe@rtone.fr>
This changes the API of xfa from
XFA(array_name, prio) type element_name = INITIALIZER;
to
XFA(type, array_name, prio) element_name = INITIALIZER;
this allows forcing natural alignment of the type, fixing failing tests
on `native64`.
Since https://github.com/RIOT-OS/RIOT/pull/20935 gpio_write()
uses a `bool` instead of an `int`. This does the same treatment for
`gpio_read()`.
This does indeed add an instruction to `gpio_read()` implementations.
However, users caring about an instruction more are better served with
`gpio_ll_read()` anyway. And `gpio_read() == 1` is often seen in
newcomer's code, which would now work as expected.
The assumption that every MCU has this feature turned out wrong. Hence,
add a feature to allow testing for support of edge triggered IRQs on
both flanks.
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
Following best practice, this patch adds the module's header as its
first include. Resulting compiler errors are also fixed by adding the
header's missing include of cpu_conf.h.
This patch allows boards to select a max ADC clock speed. This could be
handy if the board wants to clock the ADC differently according to the
board's front end analog circuitry or MCU model's ADC capabilities.
This block of code inconsistently made use of else-if statments. The
patch makes the use consistent. The change also makes the code a bit
simpler to read.
APB12 is never defined as a macro. It is an element in the bus_t enum.
Therefore, the test to check if it is defined will always fail.
APB12 is not a real bus. It is the second register of the APB1 bus. I am
not aware of any STM32 family where the ABP2 bus is implmented (ie
RCC_APB2ENR_SYSCFGEN is defined) and devices attached to said bus are
enabled via the APB1 second register. For this reason, the fix is to
simply remove the check.