Skip to content

Commit 457b6cb

Browse files
ABESTMkartben
authored andcommitted
driver: dma: stm32u5 Optimize circular mode
This removes big structures allocated on stack. It also moves linked list node to dedicated buffer. Signed-off-by: Adam Berlinger <[email protected]>
1 parent a4b819f commit 457b6cb

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

drivers/dma/dma_stm32.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ struct dma_stm32_config {
4444
uint8_t offset; /* position in the list of dmamux channel list */
4545
#endif
4646
struct dma_stm32_stream *streams;
47+
#ifdef CONFIG_DMA_STM32U5
48+
volatile uint32_t *linked_list_buffer;
49+
#endif
4750
};
4851

4952
uint32_t dma_stm32_id_to_stream(uint32_t id);

drivers/dma/dma_stm32u5.c

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ LOG_MODULE_REGISTER(dma_stm32, CONFIG_DMA_LOG_LEVEL);
2424

2525
#define DT_DRV_COMPAT st_stm32u5_dma
2626

27+
#define STM32U5_DMA_LINKED_LIST_NODE_SIZE (2)
28+
2729
static const uint32_t table_src_size[] = {
2830
LL_DMA_SRC_DATAWIDTH_BYTE,
2931
LL_DMA_SRC_DATAWIDTH_HALFWORD,
@@ -354,14 +356,6 @@ static int dma_stm32_configure(const struct device *dev,
354356
uint32_t ll_direction;
355357
int ret;
356358

357-
/* Linked list Node and structure initialization */
358-
static LL_DMA_LinkNodeTypeDef Node_GPDMA_Channel;
359-
LL_DMA_InitLinkedListTypeDef DMA_InitLinkedListStruct;
360-
LL_DMA_InitNodeTypeDef NodeConfig;
361-
362-
LL_DMA_ListStructInit(&DMA_InitLinkedListStruct);
363-
LL_DMA_NodeStructInit(&NodeConfig);
364-
365359
/* Give channel from index 0 */
366360
id = id - STM32_DMA_STREAM_OFFSET;
367361

@@ -434,10 +428,6 @@ static int dma_stm32_configure(const struct device *dev,
434428
LL_DMA_ConfigAddresses(dma, dma_stm32_id_to_stream(id), config->head_block->source_address,
435429
config->head_block->dest_address);
436430

437-
NodeConfig.SrcAddress = config->head_block->source_address;
438-
NodeConfig.DestAddress = config->head_block->dest_address;
439-
NodeConfig.BlkDataLength = config->head_block->block_size;
440-
441431
ret = dma_stm32_get_priority(config->channel_priority, &ll_priority);
442432
if (ret < 0) {
443433
return ret;
@@ -502,30 +492,41 @@ static int dma_stm32_configure(const struct device *dev,
502492
LL_DMA_SetPeriphRequest(dma, dma_stm32_id_to_stream(id), config->dma_slot);
503493

504494
if (config->head_block->source_reload_en == 0) {
495+
LL_DMA_SetLinkStepMode(dma, dma_stm32_id_to_stream(id), LL_DMA_LSM_1LINK_EXECUTION);
505496
/* Initialize the DMA structure in non-cyclic mode only */
506497
LL_DMA_SetLinkedListAddrOffset(dma, dma_stm32_id_to_stream(id), 0);
507498
} else {/* cyclic mode */
508-
/* Setting GPDMA request */
509-
NodeConfig.DestDataWidth = table_dst_size[index];
510-
NodeConfig.SrcDataWidth = table_src_size[index];
511-
NodeConfig.DestIncMode = LL_DMA_GetDestIncMode(dma, dma_stm32_id_to_stream(id));
512-
NodeConfig.SrcIncMode = LL_DMA_GetSrcIncMode(dma, dma_stm32_id_to_stream(id));
513-
NodeConfig.Direction = ll_direction;
514-
NodeConfig.Request = config->dma_slot;
499+
uint32_t linked_list_flags = 0;
500+
volatile uint32_t *linked_list_node =
501+
&dev_config->linked_list_buffer[id * STM32U5_DMA_LINKED_LIST_NODE_SIZE];
502+
/* We use "linked list" to emulate circular mode.
503+
* The linked list can consists of just source and/or destination address.
504+
* Other registers can remain the same. Linked list itself doesn't contain
505+
* pointer to other item, since LLR register is not updated (ULL bit = 0).
506+
*/
507+
if (config->head_block->source_addr_adj == config->head_block->dest_addr_adj) {
508+
/* We update both source and destination address */
509+
linked_list_node[0] = config->head_block->source_address;
510+
linked_list_node[1] = config->head_block->dest_address;
511+
linked_list_flags = LL_DMA_UPDATE_CSAR | LL_DMA_UPDATE_CDAR;
512+
} else if (config->head_block->source_addr_adj == DMA_ADDR_ADJ_INCREMENT) {
513+
/* We update only source address */
514+
linked_list_node[0] = config->head_block->source_address;
515+
linked_list_flags = LL_DMA_UPDATE_CSAR;
516+
} else if (config->head_block->dest_addr_adj == DMA_ADDR_ADJ_INCREMENT) {
517+
/* We update only destination address */
518+
linked_list_node[0] = config->head_block->dest_address;
519+
linked_list_flags = LL_DMA_UPDATE_CDAR;
520+
}
521+
/* We update only destination address */
522+
LL_DMA_SetLinkedListBaseAddr(dma, dma_stm32_id_to_stream(id),
523+
(uint32_t)&linked_list_node[0]);
524+
LL_DMA_ConfigLinkUpdate(dma, dma_stm32_id_to_stream(id), linked_list_flags,
525+
(uint32_t)&linked_list_node[0]);
515526

516527
/* Continuous transfers with Linked List */
517528
stream->cyclic = true;
518-
LL_DMA_List_Init(dma, dma_stm32_id_to_stream(id), &DMA_InitLinkedListStruct);
519-
LL_DMA_CreateLinkNode(&NodeConfig, &Node_GPDMA_Channel);
520-
LL_DMA_ConnectLinkNode(&Node_GPDMA_Channel, LL_DMA_CLLR_OFFSET5,
521-
&Node_GPDMA_Channel, LL_DMA_CLLR_OFFSET5);
522-
LL_DMA_SetLinkedListBaseAddr(dma, dma_stm32_id_to_stream(id),
523-
(uint32_t)&Node_GPDMA_Channel);
524-
LL_DMA_ConfigLinkUpdate(dma, dma_stm32_id_to_stream(id),
525-
(LL_DMA_UPDATE_CTR1 | LL_DMA_UPDATE_CTR2 |
526-
LL_DMA_UPDATE_CBR1 | LL_DMA_UPDATE_CSAR |
527-
LL_DMA_UPDATE_CDAR | LL_DMA_UPDATE_CLLR),
528-
(uint32_t)&Node_GPDMA_Channel);
529+
LL_DMA_SetLinkStepMode(dma, dma_stm32_id_to_stream(id), LL_DMA_LSM_FULL_EXECUTION);
529530

530531
LL_DMA_EnableIT_HT(dma, dma_stm32_id_to_stream(id));
531532
}
@@ -801,6 +802,11 @@ static struct dma_stm32_stream \
801802
dma_stm32_streams_##index[DT_INST_PROP_OR(index, dma_channels, \
802803
DT_NUM_IRQS(DT_DRV_INST(index)))]; \
803804
\
805+
static volatile uint32_t dma_stm32_linked_list_buffer##index \
806+
[STM32U5_DMA_LINKED_LIST_NODE_SIZE * \
807+
DT_INST_PROP_OR(index, dma_channels, \
808+
DT_NUM_IRQS(DT_DRV_INST(index)))] __nocache_noinit; \
809+
\
804810
const struct dma_stm32_config dma_stm32_config_##index = { \
805811
.pclken = { .bus = DT_INST_CLOCKS_CELL(index, bus), \
806812
.enr = DT_INST_CLOCKS_CELL(index, bits) }, \
@@ -810,6 +816,7 @@ const struct dma_stm32_config dma_stm32_config_##index = { \
810816
DT_NUM_IRQS(DT_DRV_INST(index)) \
811817
), \
812818
.streams = dma_stm32_streams_##index, \
819+
.linked_list_buffer = dma_stm32_linked_list_buffer##index \
813820
}; \
814821
\
815822
static struct dma_stm32_data dma_stm32_data_##index = { \

0 commit comments

Comments
 (0)