You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/02/19 13:28:34 UTC

[incubator-nuttx] 02/02: armv7-m: Ensure RBAR alignment

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch pr304
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 942fa2286b06a519a1c637b43e1a9fe7524357cd
Author: YAMAMOTO Takashi <ya...@midokura.com>
AuthorDate: Wed Feb 19 16:49:22 2020 +0900

    armv7-m: Ensure RBAR alignment
    
    Fix crashes on init task startup I observed on
    qemu-system-arm -M lm3s6965evb.
---
 arch/arm/src/armv7-m/mpu.h | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/arm/src/armv7-m/mpu.h b/arch/arm/src/armv7-m/mpu.h
index bcc3c0c..0a5c4de 100644
--- a/arch/arm/src/armv7-m/mpu.h
+++ b/arch/arm/src/armv7-m/mpu.h
@@ -282,6 +282,23 @@ static inline void mpu_configure_region(uintptr_t base, size_t size,
   uint32_t     regval;
   uint8_t      l2size;
   uint8_t      subregions;
+  uintptr_t    alignedbase;
+
+  /* Ensure the base address alignment
+   *
+   * ARMv7-M Architecture Reference Manual
+   * B3.5.8 MPU Region Base Address Register, MPU_RBAR
+   * "Software must ensure that the value written to the ADDR field
+   * aligns with the size of the selected region."
+   */
+  alignedbase = base & MPU_RBAR_ADDR_MASK;
+  l2size = mpu_log2regionceil(size + base - alignedbase);
+  alignedbase &= ~((1 << l2size) - 1);
+  l2size = mpu_log2regionceil(size + base - alignedbase);
+  DEBUGASSERT(alignedbase + (1 << l2size) >= base + size);
+  DEBUGASSERT(l2size == 5 || alignedbase + (1 << (l2size - 1)) < base + size);
+  DEBUGASSERT((alignedbase & MPU_RBAR_ADDR_MASK) == alignedbase);
+  DEBUGASSERT((alignedbase & ((1 << l2size) - 1)) == 0);
 
   /* Select the region */
 
@@ -289,11 +306,10 @@ static inline void mpu_configure_region(uintptr_t base, size_t size,
 
   /* Select the region base address */
 
-  putreg32((base & MPU_RBAR_ADDR_MASK) | region | MPU_RBAR_VALID, MPU_RBAR);
+  putreg32(alignedbase | region | MPU_RBAR_VALID, MPU_RBAR);
 
   /* Select the region size and the sub-region map */
 
-  l2size     = mpu_log2regionceil(size);
   subregions = mpu_subregion(base, size, l2size);
 
   /* The configure the region */