-
Notifications
You must be signed in to change notification settings - Fork 7.3k
cache: stm32: add cortex-m33 peripheral driver #88585
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
kartben
merged 3 commits into
zephyrproject-rtos:main
from
lindblandro:stm32-cache-peripheral-driver
Apr 25, 2025
Merged
Changes from all commits
Commits
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
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
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,24 @@ | ||
# Copyright (c) 2025 Henrik Lindblom <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
menuconfig CACHE_STM32 | ||
bool "STM32 cache driver" | ||
select CACHE_HAS_DRIVER | ||
depends on CACHE_MANAGEMENT | ||
help | ||
Enable support for the STM32 ICACHE / DCACHE peripheral present in some STM32 chips. | ||
|
||
if CACHE_STM32 | ||
|
||
# "default n" for L5 is legacy - could be removed? | ||
config CACHE_STM32_ICACHE_DIRECT_MAPPING | ||
bool "Use 1-way associative mapping for ICACHE" | ||
default n if SOC_SERIES_STM32L5X | ||
default y | ||
help | ||
Use ICACHE in direct mapping (1-way associative) mode instead of the default n-way | ||
associative cache mode. | ||
|
||
This option reduces power consumption but slightly reduces cache's performance. | ||
|
||
endif # CACHE_STM32 |
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,182 @@ | ||
/* | ||
* Copyright (c) 2025 Henrik Lindblom <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/drivers/cache.h> | ||
#include <zephyr/logging/log.h> | ||
#include <zephyr/sys/math_extras.h> | ||
#include <stm32_ll_dcache.h> | ||
#include <stm32_ll_icache.h> | ||
|
||
LOG_MODULE_REGISTER(cache_stm32, CONFIG_CACHE_LOG_LEVEL); | ||
|
||
#ifdef CONFIG_DCACHE | ||
|
||
void cache_data_enable(void) | ||
{ | ||
LL_DCACHE_Enable(DCACHE1); | ||
#if defined(DCACHE2) | ||
LL_DCACHE_Enable(DCACHE2); | ||
#endif | ||
} | ||
|
||
void cache_data_disable(void) | ||
{ | ||
cache_data_flush_all(); | ||
|
||
while (LL_DCACHE_IsActiveFlag_BUSYCMD(DCACHE1)) { | ||
} | ||
|
||
LL_DCACHE_Disable(DCACHE1); | ||
LL_DCACHE_ClearFlag_BSYEND(DCACHE1); | ||
|
||
#if defined(DCACHE2) | ||
while (LL_DCACHE_IsActiveFlag_BUSYCMD(DCACHE2)) { | ||
} | ||
|
||
LL_DCACHE_Disable(DCACHE2); | ||
LL_DCACHE_ClearFlag_BSYEND(DCACHE2); | ||
#endif | ||
} | ||
|
||
static int cache_data_manage_range(void *addr, size_t size, uint32_t command) | ||
{ | ||
/* | ||
* This is a simple approach to invalidate the range. The address might be in either DCACHE1 | ||
* or DCACHE2 (if present). The cache invalidation algorithm checks the TAG memory for the | ||
* specified address range so there's little harm in just checking both caches. | ||
*/ | ||
uint32_t start = (uint32_t)addr; | ||
uint32_t end; | ||
|
||
if (u32_add_overflow(start, size, &end)) { | ||
return -EOVERFLOW; | ||
} | ||
|
||
LL_DCACHE_SetStartAddress(DCACHE1, start); | ||
LL_DCACHE_SetEndAddress(DCACHE1, end); | ||
LL_DCACHE_SetCommand(DCACHE1, command); | ||
LL_DCACHE_StartCommand(DCACHE1); | ||
#if defined(DCACHE2) | ||
LL_DCACHE_SetStartAddress(DCACHE2, start); | ||
LL_DCACHE_SetEndAddress(DCACHE2, end); | ||
LL_DCACHE_SetCommand(DCACHE2, command); | ||
LL_DCACHE_StartCommand(DCACHE2); | ||
#endif | ||
return 0; | ||
} | ||
|
||
int cache_data_flush_range(void *addr, size_t size) | ||
{ | ||
return cache_data_manage_range(addr, size, LL_DCACHE_COMMAND_CLEAN_BY_ADDR); | ||
} | ||
|
||
int cache_data_invd_range(void *addr, size_t size) | ||
{ | ||
return cache_data_manage_range(addr, size, LL_DCACHE_COMMAND_INVALIDATE_BY_ADDR); | ||
} | ||
|
||
int cache_data_flush_and_invd_range(void *addr, size_t size) | ||
{ | ||
return cache_data_manage_range(addr, size, LL_DCACHE_COMMAND_CLEAN_INVALIDATE_BY_ADDR); | ||
} | ||
|
||
int cache_data_flush_all(void) | ||
{ | ||
return cache_data_flush_range(0, UINT32_MAX); | ||
} | ||
|
||
int cache_data_invd_all(void) | ||
{ | ||
LL_DCACHE_Invalidate(DCACHE1); | ||
#if defined(DCACHE2) | ||
LL_DCACHE_Invalidate(DCACHE2); | ||
#endif | ||
return 0; | ||
} | ||
|
||
int cache_data_flush_and_invd_all(void) | ||
{ | ||
return cache_data_flush_and_invd_range(0, UINT32_MAX); | ||
} | ||
|
||
#endif /* CONFIG_DCACHE */ | ||
|
||
static inline void wait_for_icache(void) | ||
{ | ||
while (LL_ICACHE_IsActiveFlag_BUSY()) { | ||
} | ||
|
||
/* Clear BSYEND to avoid an extra interrupt if somebody enables them. */ | ||
LL_ICACHE_ClearFlag_BSYEND(); | ||
} | ||
|
||
void cache_instr_enable(void) | ||
{ | ||
if (IS_ENABLED(CONFIG_CACHE_STM32_ICACHE_DIRECT_MAPPING)) { | ||
LL_ICACHE_SetMode(LL_ICACHE_1WAY); | ||
} | ||
|
||
/* | ||
* Need to wait until any pending cache invalidation operations finish. This is recommended | ||
* in the reference manual to ensure execution timing determinism. | ||
*/ | ||
wait_for_icache(); | ||
LL_ICACHE_Enable(); | ||
} | ||
|
||
void cache_instr_disable(void) | ||
{ | ||
LL_ICACHE_Disable(); | ||
lindblandro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
while (LL_ICACHE_IsEnabled()) { | ||
/** | ||
* Wait until the ICACHE is disabled (CR.EN=0), at which point | ||
* all requests bypass the cache and are forwarded directly | ||
* from the ICACHE slave port to the ICACHE master port(s). | ||
* | ||
* The cache invalidation will start once disabled, but we allow | ||
* it to proceed in the background since it doesn't need to be | ||
* complete for requests to bypass the ICACHE. | ||
*/ | ||
} | ||
} | ||
|
||
int cache_instr_flush_all(void) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int cache_instr_invd_all(void) | ||
{ | ||
LL_ICACHE_Invalidate(); | ||
return 0; | ||
} | ||
|
||
int cache_instr_flush_and_invd_all(void) | ||
{ | ||
return -ENOTSUP; | ||
} | ||
|
||
int cache_instr_flush_range(void *addr, size_t size) | ||
{ | ||
ARG_UNUSED(addr); | ||
ARG_UNUSED(size); | ||
return -ENOTSUP; | ||
} | ||
|
||
int cache_instr_invd_range(void *addr, size_t size) | ||
{ | ||
ARG_UNUSED(addr); | ||
ARG_UNUSED(size); | ||
return -ENOTSUP; | ||
} | ||
|
||
int cache_instr_flush_and_invd_range(void *addr, size_t size) | ||
{ | ||
ARG_UNUSED(addr); | ||
ARG_UNUSED(size); | ||
return -ENOTSUP; | ||
} |
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.
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.
I think it should be ok to move L5 to 1-way associated mapping, but we should document the change in migration guide and mention how to revert.
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.
Yes it's probably fine, but I'd suggest doing that in a separate PR.