-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
drivers: use codegen for device instantiation #10888
Changes from all commits
0dd210c
bd05cb5
6d7e50f
b6d36f4
0f9247d
fee96d1
320a8f2
14efbdc
67ad920
08fb2e9
3cebfd3
be75e68
6350298
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
zephyr_sources_ifdef(CONFIG_CAN_STM32 stm32_can.c) | ||
zephyr_sources_codegen_ifdef(CONFIG_CAN_STM32 stm32_can.c) | ||
zephyr_sources_ifdef(CONFIG_USERSPACE can_handlers.c) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -841,51 +841,66 @@ static const struct can_driver_api can_api_funcs = { | |
.detach = can_stm32_detach | ||
}; | ||
|
||
#ifdef CONFIG_CAN_1 | ||
|
||
static void config_can_1_irq(CAN_TypeDef *can); | ||
|
||
static const struct can_stm32_config can_stm32_cfg_1 = { | ||
.can = (CAN_TypeDef *)DT_CAN_1_BASE_ADDRESS, | ||
.bus_speed = DT_CAN_1_BUS_SPEED, | ||
.swj = DT_CAN_1_SJW, | ||
.prop_bs1 = DT_CAN_1_PROP_SEG_PHASE_SEG1, | ||
.bs2 = DT_CAN_1_PHASE_SEG2, | ||
.pclken = { | ||
.enr = DT_CAN_1_CLOCK_BITS, | ||
.bus = DT_CAN_1_CLOCK_BUS, | ||
}, | ||
.config_irq = config_can_1_irq | ||
}; | ||
|
||
static struct can_stm32_data can_stm32_dev_data_1; | ||
|
||
DEVICE_AND_API_INIT(can_stm32_1, DT_CAN_1_NAME, &can_stm32_init, | ||
&can_stm32_dev_data_1, &can_stm32_cfg_1, | ||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, | ||
&can_api_funcs); | ||
|
||
static void config_can_1_irq(CAN_TypeDef *can) | ||
{ | ||
LOG_DBG("Enable CAN1 IRQ"); | ||
#ifdef CONFIG_SOC_SERIES_STM32F0X | ||
IRQ_CONNECT(DT_CAN_1_IRQ, DT_CAN_1_IRQ_PRIORITY, can_stm32_isr, | ||
DEVICE_GET(can_stm32_1), 0); | ||
irq_enable(DT_CAN_1_IRQ); | ||
#else | ||
IRQ_CONNECT(DT_CAN_1_IRQ_RX0, DT_CAN_1_IRQ_PRIORITY, | ||
can_stm32_rx_isr, DEVICE_GET(can_stm32_1), 0); | ||
irq_enable(DT_CAN_1_IRQ_RX0); | ||
|
||
IRQ_CONNECT(DT_CAN_1_IRQ_TX, DT_CAN_1_IRQ_PRIORITY, | ||
can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0); | ||
irq_enable(DT_CAN_1_IRQ_TX); | ||
|
||
IRQ_CONNECT(DT_CAN_1_IRQ_SCE, DT_CAN_1_IRQ_PRIORITY, | ||
can_stm32_tx_isr, DEVICE_GET(can_stm32_1), 0); | ||
irq_enable(DT_CAN_1_IRQ_SCE); | ||
#endif | ||
can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1; | ||
} | ||
|
||
#endif /*CONFIG_CAN_1*/ | ||
/** | ||
* @code{.cogeno.py} | ||
* cogeno.import_module('devicedeclare') | ||
* | ||
* device_configs = ['CONFIG_CAN_1', ] | ||
* driver_names = ['CAN_1', ] | ||
* device_inits = 'can_stm32_init' | ||
* device_levels = 'POST_KERNEL' | ||
* device_prios = 'CONFIG_KERNEL_INIT_PRIORITY_DEVICE' | ||
* device_api = 'can_api_funcs' | ||
* device_info = \ | ||
* """ | ||
* DEVICE_DECLARE(${device-name}); | ||
* static void ${device-config-irq}(CAN_TypeDef *can) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole piece of code, IRQ configuration functions, should be extracted by API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know your opinion. This is just to show the principle. You can use your device_declare variant here also. Your variant will fail with STM32F0 UART drivers. A lot of shared interrupts where you definitely need a more sofisticated way to generate interrupt routines. The driver is OOT but I can tell it definitely did not work with the driver_declare interrupt configuration - your one and also not the simple one that I have here. |
||
* { | ||
* LOG_DBG("Enable ${driver-name} IRQ"); | ||
* #ifdef CONFIG_SOC_SERIES_STM32F0X | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'compatible' should be used to identify and provide variations of the same driver. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey this is a proof of concept and not a full blown driver rework, I expect the CAN driver author to do the rework in the end when there is a code generation facility. My focus was the extraction of device tree data not to make that work without some ifdefs. |
||
* IRQ_CONNECT(${interrupts/0/irq}, ${interrupts/0/priority},\\ | ||
* can_stm32_isr, | ||
* DEVICE_GET(${device-name}), 0); | ||
* irq_enable(${interrupts/0/irq}); | ||
* #else | ||
* IRQ_CONNECT(${interrupts/rx0/irq}, ${interrupts/rx0/priority}, \\ | ||
* can_stm32_rx_isr, | ||
* DEVICE_GET(${device-name}), 0); | ||
* irq_enable(${interrupts/rx0/irq}); | ||
* IRQ_CONNECT(${interrupts/tx/irq}, ${interrupts/tx/priority}, \\ | ||
* can_stm32_tx_isr, | ||
* DEVICE_GET(${device-name}), 0); | ||
* irq_enable(${interrupts/tx/irq}); | ||
* IRQ_CONNECT(${interrupts/sce/irq}, ${interrupts/sce/priority}, \\ | ||
* can_stm32_tx_isr, | ||
* DEVICE_GET(${device-name}), 0); | ||
* irq_enable(${interrupts/sce/irq}); | ||
* #endif | ||
* can->IER |= CAN_IT_TME | CAN_IT_ERR | CAN_IT_FMP0 | CAN_IT_FMP1; | ||
* } | ||
* static const struct can_stm32_config ${device-config-info} = { | ||
* .can = (CAN_TypeDef *)${reg/0/address/0}, | ||
* .bus_speed = ${bus-speed}, | ||
* .swj = ${sjw}, | ||
* .prop_bs1 = ${prop_seg_phase_seg1}, | ||
* .bs2 = ${phase_seg2}, | ||
* .pclken = { | ||
* .enr = ${clocks/0/bits}, | ||
* .bus = ${clocks/0/bus}, | ||
* }, | ||
* .config_irq = ${device-config-irq}, | ||
* }; | ||
* static struct can_stm32_data ${device-data}; | ||
* """ | ||
* | ||
* devicedeclare.device_declare_multi( \ | ||
* device_configs, | ||
* driver_names, | ||
* device_inits, | ||
* device_levels, | ||
* device_prios, | ||
* device_api, | ||
* device_info) | ||
* @endcode{.cogeno.py} | ||
*/ | ||
/** @code{.cogeno.ins}@endcode */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned several times, this should not be present in API.
This information should be extracted from device tree and drivers <> EDTS binding should be done by 'compatible' property. This is literally its main and only use.
cf #8561
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentionend several times to identify a specific driver instance the compatible is not enough. There are usual several driver instantiations for one compatible. So you need something more to identify a single one and use the 'label' property for that. But if you use the 'label' property in addition to the 'compatible' you find out that the 'label' alone is unique und you really do not need the 'compatible'. Taking the 'compatible' and the 'label' is just a waste of computing.
If you would look into the code of your device_declare variant you could easily identify that in the end only the 'label' is used.