Skip to content
This repository has been archived by the owner on Jan 22, 2022. It is now read-only.

Commit

Permalink
Merged SAME5x and SAM4E cache management code
Browse files Browse the repository at this point in the history
  • Loading branch information
dc42 committed Dec 1, 2020
1 parent 438e008 commit 48727ca
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 63 deletions.
137 changes: 79 additions & 58 deletions cores/arduino/Cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "Cache.h"

#if !SAMC21 && !SAM4S && !SAM3XA
#if SAM4E || SAME70 || SAME5x

#if SAME70
# include <core_cm7.h>
Expand All @@ -17,6 +17,8 @@
extern uint32_t _nocache_ram_start;
extern uint32_t _nocache_ram_end;

static bool cacheEnabled = false;

# if USE_MPU
# include <mpu_armv7.h>

Expand All @@ -43,40 +45,61 @@ extern uint32_t _nocache_ram_end;

# endif

#endif
#else

#if SAM4E
# include <cmcc/cmcc.h>
// SAM4E and SAME5x use fairly similar cache controllers

inline bool is_cache_enabled() noexcept
{
#if SAME5x
return CMCC->SR.bit.CSTS;
#elif SAM4E
return (CMCC->CMCC_SR & CMCC_SR_CSTS) != 0;
#endif
}

inline void cache_invalidate_all() noexcept
{
#if SAME5x
CMCC->MAINT0.reg = CMCC_MAINT0_INVALL;
#elif SAM4E
CMCC->CMCC_MAINT0 = CMCC_MAINT0_INVALL;
#endif
__ISB();
__DSB();
}

inline void cache_disable()
inline void cache_disable() noexcept
{
while (CMCC->SR.bit.CSTS)
while (is_cache_enabled())
{
#if SAME5x
CMCC->CTRL.reg = 0;
#elif SAM4E
CMCC->CMCC_CTRL = 0;
#endif
__ISB();
__DSB();
}
}

inline void cache_enable()
{
CMCC->CTRL.reg = CMCC_CTRL_CEN;
__ISB();
__DSB();
}

inline void cache_invalidate_all()
inline void cache_enable() noexcept
{
CMCC->MAINT0.reg = CMCC_MAINT0_INVALL;
if (!is_cache_enabled())
{
cache_invalidate_all();
#if SAME5x
CMCC->CTRL.reg = CMCC_CTRL_CEN;
#elif SAM4E
CMCC->CMCC_CTRL = CMCC_CTRL_CEN;
#endif
__ISB();
__DSB();
}
}

#endif

static bool enabled = false;

void Cache::Init() noexcept
{
#if SAME70
Expand Down Expand Up @@ -169,55 +192,51 @@ void Cache::Init() noexcept
# endif

#elif SAME5x
// No need to do any initialisation
CMCC->MCFG.reg = CMCC_MCFG_MODE_DHIT_COUNT; // data hit mode
CMCC->MEN.bit.MENABLE = 1;
#elif SAM4E
CMCC->CMCC_MCFG = CMCC_DHIT_COUNT_MODE;
CMCC->CMCC_MCFG = 2; // data hit mode
CMCC->CMCC_MEN |= CMCC_MEN_MENABLE;
#endif
}

void Cache::Enable() noexcept
{
if (!enabled)
{
enabled = true;
#if SAME70
if (!cacheEnabled)
{
cacheEnabled = true;
SCB_EnableICache();
SCB_EnableDCache();
#elif SAME5x
cache_invalidate_all();
cache_enable();
#elif SAM4E
CMCC->CMCC_MAINT0 = CMCC_MAINT0_INVALL; // invalidate all lines
CMCC->CMCC_CTRL = CMCC_CTRL_CEN; // enable cache
#endif
}
#else
cache_enable();
#endif
}

// Disable the cache, returning true if it was enabled
bool Cache::Disable() noexcept
{
if (enabled)
{
#if SAME70
const bool wasEnabled = cacheEnabled;
if (wasEnabled)
{
SCB_DisableICache();
SCB_DisableDCache(); // this cleans it as well as disabling it
#elif SAME5x
cache_disable();
#elif SAM4E
CMCC->CMCC_CTRL = 0; // disable cache
#endif
enabled = false;
return true;
cacheEnabled = false;
}
return false;
#else
const bool wasEnabled = is_cache_enabled();
cache_disable();
#endif
return wasEnabled;
}

#if SAME70

void Cache::Flush(const volatile void *start, size_t length) noexcept
{
if (enabled)
if (cacheEnabled)
{
// We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area
if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end)
Expand All @@ -232,47 +251,49 @@ void Cache::Flush(const volatile void *start, size_t length) noexcept

void Cache::Invalidate(const volatile void *start, size_t length) noexcept
{
if (enabled)
{
#if SAME70
if (cacheEnabled)
{
// We assume that the DMA buffer is entirely inside or entirely outside the non-cached RAM area
if (start < (void*)&_nocache_ram_start || start >= (void*)&_nocache_ram_end)
{
// Caution! if any part of the cache line is dirty, the written data will be lost!
const uint32_t startAddr = reinterpret_cast<uint32_t>(start);
SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t*>(startAddr & ~3), length + (startAddr & 3));
}
#elif SAME5x
//TODO can we invalidate just the relevant cache line(s)?
// Disable interrupts throughout the sequence, otherwise we could get a task switch while the cache is disabled.
// The can cause a crash because we end up invalidating the cache while it is enabled.
}
#else
// We just invalidate the whole cache
if (is_cache_enabled())
{
// Disable interrupts to prevent a task switch, otherwise we may end up with the cache disabled in another task
const irqflags_t flags = cpu_irq_save();
cache_disable();
cache_invalidate_all();
cache_enable();
cpu_irq_restore(flags);
#elif SAM4E
// The cache is only 2kb on the SAM4E so we just invalidate the whole cache
const irqflags_t flags = cpu_irq_save();
CMCC->CMCC_CTRL = 0; // disable cache
__ISB();
CMCC->CMCC_MAINT0 = CMCC_MAINT0_INVALL; // invalidate all lines
CMCC->CMCC_CTRL = CMCC_CTRL_CEN; // enable cache
cpu_irq_restore(flags);
#endif
}
else
{
cache_invalidate_all();
}
#endif
}

#if SAM4E
#if SAM4E || SAME5x

uint32_t Cache::GetHitCount() noexcept
{
return cmcc_get_monitor_cnt(CMCC);
#if SAM4E
return CMCC->CMCC_MSR;
#elif SAME5x
return CMCC->MSR.reg;
#endif
}

#endif

#endif // !SAMC21 && !SAM4S && !SAM3XA
#endif // SAM4E || SAME70 || SAME5x

// Entry points that can be called from ASF C code
void CacheFlushBeforeDMAReceive(const volatile void *start, size_t length) noexcept { Cache::FlushBeforeDMAReceive(start, length); }
Expand Down
10 changes: 5 additions & 5 deletions cores/arduino/Cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* Author: David
*/

#ifndef SRC_HARDWARE_CACHE_H_
#define SRC_HARDWARE_CACHE_H_
#ifndef SRC_CACHE_H_
#define SRC_CACHE_H_

#include <Core.h>

Expand All @@ -22,7 +22,7 @@ namespace Cache
inline void InvalidateAfterDMAReceive(const volatile void *start, size_t length) noexcept { Invalidate(start, length); }
inline void FlushBeforeDMASend(const volatile void *start, size_t length) noexcept { Flush(start, length); }

#if SAM4E
#if SAM4E || SAME5x
uint32_t GetHitCount() noexcept;
#endif
};
Expand All @@ -43,9 +43,9 @@ inline void Cache::Invalidate(const volatile void *start, size_t length) noexcep

#elif SAM4E || SAME5x

// The SAM4E cache is write-through, so no need to flush it
// The SAM4E and SAME5x cache is write-through, so no need to flush it
inline void Cache::Flush(const volatile void *start, size_t length) noexcept { __DSB(); }

#endif

#endif /* SRC_HARDWARE_CACHE_H_ */
#endif /* SRC_CACHE_H_ */

0 comments on commit 48727ca

Please sign in to comment.