arch: armv7-m: mpu: disable shareable bit in _get_mpu_ram_region_attr()

In Zephyr on Cortex-M SoCs with both the ARM MPU and the cache enabled,
there are 3 possible states and associated configuration for the RAM
cache attributes:

- MPU disabled                        WBWA non-shareable
- MPU enabled, background RAM region  WBWA non-shareable
- MPU enabled, thread RAM region      WBWA shareable

In practice this means than the thread RAM region toggles from
shareable to non-shareable on each context change.

However the Cortex-M7 SoC does not support the WBWA shareable
configuration and fallback to simpler caching configuration. The
Technical Reference Manual states:

  "By default, only Normal, Non-shareable memory regions can be cached
  in the RAMs. Caching only takes place if the appropriate cache is
  enabled and the memory type is cacheable. Shared cacheable memory
  regions can be cached if CACR.SIWT is set to 1."

Similar indications can be found in the documentation from various
vendors: ST (AN4838), NXP (AN12042) and Atmel (AN15679).

It means that the thread RAM regions are either not cached (CACR.SIWT=0,
default) or WBWT cached (CACR.SIWT=1). This causes a performance issue.
In addition before switching a region from cached to non-cached and
vice-versa, the existing MPU code does not perform cache clean and/or
invalidate operations. This might cause data loss or corruption.

We should therefore change the RAM cache attributes to make them always
consistent. This patches change the thread/application RAM region from
WBWA shareable to WBWA non-shareable. This is done for all ARMv7-M SoCs
with an ARM MPU, however other SoCs (M0+, M3, M4) do not have cache, so
their behaviour should be unchanged.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2018-11-07 20:49:44 +01:00 committed by Anas Nashif
commit 1397269335

View file

@ -103,7 +103,7 @@ static inline void _get_mpu_ram_region_attr(arm_mpu_region_attr_t *p_attr,
*/ */
(void) base; (void) base;
p_attr->rasr = _get_region_attr(1, ap, 1, 1, 1, 1, 0, size); p_attr->rasr = _get_region_attr(1, ap, 1, 1, 1, 0, 0, size);
} }
/** /**