-
Notifications
You must be signed in to change notification settings - Fork 130
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
Enable D-Cache for Cortex-M7 #485
Comments
I had this already on my list since I was wondering why the I-Cache is enabled, but not the D-Cache. First time I saw this when porting the FreeRTOS HAL based network interface, but at least for the M7 the macro does nothing to invalidate the cache. |
Yes, I just remembered this due to getting confused about DTCM with D-Cache while fixing the DTCM size bug. I wasn't sure during porting what the invalidation required from an modm API perspective, so I just disabled it. Not great, not terrible. |
Leaving this here for my future self: |
Also good: https://alexkalmuk.medium.com/cpu-caches-with-examples-for-arm-cortex-m-2c05a339246e We should enable the D-Cache at least with write-through. Write-back can then be enabled by the user if required. |
Well… maybe not. Sounds like we would need support from the DMA API. |
I recently had an issue on a F765, where I enabled the D cache and Ethernet stopped working. Probably related to the DMA. |
Yeah, it seems to require application support to manually invalidate the cache when required (ie. after (during?) DMA transfers), and tbh the user can still enable the DCache in main() so there's no need for modm to enable it (wrongly). I'm instead going to add some docs on this fact to the |
There is a better solution, an MPU is really good to define cache policies. It gives better performance since you don't have to invalidate the cache, it only costs a new section in the linker script. You can see a example below on a helper class I have made to build MPU configurations. It's made in Boost style syntax but it is pretty easy to port. If you wish i can send it to you. void mpu_setup()
{
using namespace msl;
auto dma_buffers = [] {
mpu::region_builder<1, 0x38000000, 2048, mpu::region_type::normal> reg;
reg.set_cache_policy(mpu::cache_policy::non_cacheable);
reg.set_access_policy(mpu::access_policy::privileged_only);
reg.update_rnr();
reg.enable();
return reg.build();
};
constexpr auto rdb = dma_buffers();
mpu::update(rdb);
mpu::enable(mpu::mode::default_memory_map);
} |
Oh, very nice, I hadn't thought about using the MPU that way! |
The header is posted here. I have modified it so it compiles in modm. 😃 The example below is tested on a stm32h743 and it should work on any cm4 and cm7 architecture, only the number of regions needs to be changed. #include <modm/board.hpp>
#include <modm/processing.hpp>
#include <modm/platform/clock/rcc.hpp>
#include "mpu.hpp"
using namespace Board;
void mpu_setup()
{
constexpr auto const stack_sentinal = [] {
mpu::region_builder<0x24070000, 32, mpu::region_type::normal> reg;
reg.set_cache_policy(mpu::cache_policy::write_back);
reg.set_access_policy(mpu::access_policy::no_access);
reg.update_rnr(0);
reg.enable();
return reg.build();
}();
mpu::update(stack_sentinal);
constexpr auto const dma_buffers = [] {
mpu::region_builder<0x38000000, 2048, mpu::region_type::normal> reg;
reg.set_cache_policy(mpu::cache_policy::non_cacheable);
reg.set_access_policy(mpu::access_policy::privileged_only);
reg.update_rnr(1);
reg.enable();
return reg.build();
}();
mpu::update(dma_buffers);
mpu::enable(mpu::mode::default_memory_map);
}
int
main()
{
Board::initialize();
Led::setOutput();
RCC->AHB2ENR |= RCC_AHB2ENR_SRAM1EN_Msk | RCC_AHB2ENR_SRAM2EN_Msk | RCC_AHB2ENR_SRAM3EN_Msk;
mpu_setup();
[[maybe_unused]] volatile auto stack_crash = reinterpret_cast<std::uint32_t*>(0x24070000U);
*stack_crash = 0;
|
I just discovered a bug. It should be fixed in the region_builder class, the MPU is very critical with correct alignment and can give some hairy situations if it's wrong. static_assert((Address & 0x1f) == 0, "Invalid alignment");
// Should be changed to:
static_assert((Address & (Size - 1)) == 0, "Invalid alignment");
|
I love it, this is great, do you want to add a We already have a |
Yes, later... Right now missing SPI/DMA support is more important. |
Oh, I see. STM32H7 family completely is missing a SPI driver currently, see peripheral matrix. (Not sure if that is just not tested/enabled, but identical to the SPI peripherals in other STM32 families or if ST put a new SPI IP into the STM32H7 controllers which requires a new driver.) For all other targets |
The H7 SPI has a completely different register map and needs a new driver. |
The Data Cache for Cortex-M7 devices is currently disables, due to a lack of in-depth understanding of cache policies during porting. The Instruction Cache however is enabled, since it only gets read.
See: https://github.com/modm-io/modm/blob/develop/src/modm/platform/core/cortex/startup.c.in#L95-L98
In addition to enabling the cache, the caches must be invalidated manually on certain operations (writing Flash for example).
This is however not just an issue on Cortex-M7, since most Cortex-M devices have some sort of vendor specific cache implementation for their Flash reads, which must also be manually invalided.
cc @mikewolfram
The text was updated successfully, but these errors were encountered: