26
26
27
27
#include <stdint.h>
28
28
#include <assert.h>
29
+ #include <debug.h>
29
30
30
31
#include "mpu.h"
31
32
#include "arm_internal.h"
@@ -69,9 +70,9 @@ static const uint8_t g_ls_regionmask[9] =
69
70
0x00 , 0x01 , 0x03 , 0x07 , 0x0f , 0x1f , 0x3f , 0x7f , 0xff
70
71
};
71
72
72
- /* The next available region number */
73
+ /* The available region bitmap */
73
74
74
- static uint8_t g_region ;
75
+ static unsigned int g_mpu_region ;
75
76
76
77
/****************************************************************************
77
78
* Private Functions
@@ -89,6 +90,13 @@ static uint8_t g_region;
89
90
* l2size has the same properties as the return value from
90
91
* mpu_log2regionceil()
91
92
*
93
+ * Input Parameters:
94
+ * size: The size of the region.
95
+ * l2size: The L2 size of the region.
96
+ *
97
+ * Returned Value:
98
+ * The sub-region bitmask.
99
+ *
92
100
****************************************************************************/
93
101
94
102
static inline uint32_t mpu_subregion_ms (size_t size , uint8_t l2size )
@@ -140,6 +148,13 @@ static inline uint32_t mpu_subregion_ms(size_t size, uint8_t l2size)
140
148
* l2size has the same properties as the return value from
141
149
* mpu_log2regionceil()
142
150
*
151
+ * Input Parameters:
152
+ * offset: The offset of the region.
153
+ * l2size: The L2 size of the region.
154
+ *
155
+ * Returned Value:
156
+ * The sub-region bitmask.
157
+ *
143
158
****************************************************************************/
144
159
145
160
static inline uint32_t mpu_subregion_ls (size_t offset , uint8_t l2size )
@@ -184,6 +199,12 @@ static inline uint32_t mpu_subregion_ls(size_t offset, uint8_t l2size)
184
199
* Description:
185
200
* Resets the MPU to disabled.
186
201
*
202
+ * Input Parameters:
203
+ * None.
204
+ *
205
+ * Returned Value:
206
+ * None.
207
+ *
187
208
****************************************************************************/
188
209
189
210
#if defined(CONFIG_ARM_MPU_RESET ) || defined(CONFIG_ARM_MPU_EARLY_RESET )
@@ -218,17 +239,51 @@ static void mpu_reset_internal()
218
239
* Description:
219
240
* Allocate the next region
220
241
*
221
- * Assumptions:
222
- * - Regions are never deallocated
223
- * - Regions are only allocated early in initialization, so no special
224
- * protection against re-entrancy is required;
242
+ * Input Parameters:
243
+ * None
244
+ *
245
+ * Returned Value:
246
+ * The index of the allocated region.
225
247
*
226
248
****************************************************************************/
227
249
228
250
unsigned int mpu_allocregion (void )
229
251
{
230
- DEBUGASSERT (g_region < CONFIG_ARM_MPU_NREGIONS );
231
- return (unsigned int )g_region ++ ;
252
+ unsigned int i = ffs (~g_mpu_region ) - 1 ;
253
+
254
+ /* There are not enough regions to apply */
255
+
256
+ DEBUGASSERT (i < CONFIG_ARM_MPU_NREGIONS );
257
+ g_mpu_region |= 1 << i ;
258
+ return i ;
259
+ }
260
+
261
+ /****************************************************************************
262
+ * Name: mpu_freeregion
263
+ *
264
+ * Description:
265
+ * Free target region.
266
+ *
267
+ * Input Parameters:
268
+ * region - The index of the region to be freed.
269
+ *
270
+ * Returned Value:
271
+ * None
272
+ *
273
+ ****************************************************************************/
274
+
275
+ void mpu_freeregion (unsigned int region )
276
+ {
277
+ DEBUGASSERT (region < CONFIG_ARM_MPU_NREGIONS );
278
+
279
+ /* Clear and disable the given MPU Region */
280
+
281
+ putreg32 (region , MPU_RNR );
282
+ putreg32 (0 , MPU_RASR );
283
+ putreg32 (0 , MPU_RBAR );
284
+ g_mpu_region &= ~(1 << region );
285
+ ARM_DSB ();
286
+ ARM_ISB ();
232
287
}
233
288
234
289
/****************************************************************************
@@ -240,6 +295,12 @@ unsigned int mpu_allocregion(void)
240
295
*
241
296
* size <= (1 << l2size)
242
297
*
298
+ * Input Parameters:
299
+ * size - The size of the region.
300
+ *
301
+ * Returned Value:
302
+ * The logarithm base 2 of the ceiling value for the MPU region size.
303
+ *
243
304
****************************************************************************/
244
305
245
306
uint8_t mpu_log2regionceil (size_t size )
@@ -261,6 +322,12 @@ uint8_t mpu_log2regionceil(size_t size)
261
322
*
262
323
* size >= (1 << l2size)
263
324
*
325
+ * Input Parameters:
326
+ * size - The size of the region.
327
+ *
328
+ * Returned Value:
329
+ * The logarithm base 2 of the floor value for the MPU region size.
330
+ *
264
331
****************************************************************************/
265
332
266
333
uint8_t mpu_log2regionfloor (size_t size )
@@ -287,6 +354,14 @@ uint8_t mpu_log2regionfloor(size_t size)
287
354
* l2size has the same properties as the return value from
288
355
* mpu_log2regionceil()
289
356
*
357
+ * Input Parameters:
358
+ * base - The base address of the region.
359
+ * size - The size of the region.
360
+ * l2size - Log2 of the actual region size is <= (1 << l2size).
361
+ *
362
+ * Returned Value:
363
+ * The subregion settings as a 32-bit value.
364
+ *
290
365
****************************************************************************/
291
366
292
367
uint32_t mpu_subregion (uintptr_t base , size_t size , uint8_t l2size )
@@ -338,6 +413,16 @@ uint32_t mpu_subregion(uintptr_t base, size_t size, uint8_t l2size)
338
413
* Description:
339
414
* Configure and enable (or disable) the MPU
340
415
*
416
+ * Input Parameters:
417
+ * enable - Flag indicating whether to enable the MPU.
418
+ * hfnmiena - Flag indicating whether to enable the MPU during hard
419
+ * fult, NMI, and FAULTMAS.
420
+ * privdefena - Flag indicating whether to enable privileged access to
421
+ * the default memory map.
422
+ *
423
+ * Returned Value:
424
+ * None.
425
+ *
341
426
****************************************************************************/
342
427
343
428
void mpu_control (bool enable , bool hfnmiena , bool privdefena )
@@ -368,22 +453,34 @@ void mpu_control(bool enable, bool hfnmiena, bool privdefena)
368
453
}
369
454
370
455
/****************************************************************************
371
- * Name: mpu_configure_region
456
+ * Name: mpu_modify_region
372
457
*
373
458
* Description:
374
- * Configure a region for privileged, strongly ordered memory
459
+ * Modify a region for privileged, strongly ordered memory
460
+ *
461
+ * Input Parameters:
462
+ * region - Region number to modify.
463
+ * base - Base address of the region.
464
+ * size - Size of the region.
465
+ * flags - Flags to configure the region.
466
+ *
467
+ * Returned Value:
468
+ * None.
375
469
*
376
470
****************************************************************************/
377
471
378
- void mpu_configure_region ( uintptr_t base , size_t size ,
379
- uint32_t flags )
472
+ void mpu_modify_region ( unsigned int region , uintptr_t base , size_t size ,
473
+ uint32_t flags )
380
474
{
381
- unsigned int region = mpu_allocregion ();
382
475
uint32_t regval ;
383
476
uint8_t l2size ;
384
477
uint8_t subregions ;
385
478
uintptr_t alignedbase ;
386
479
480
+ /* Check that the region is valid */
481
+
482
+ DEBUGASSERT (g_mpu_region & (1 << region ));
483
+
387
484
/* Ensure the base address alignment
388
485
*
389
486
* ARMv7-M Architecture Reference Manual
@@ -429,13 +526,124 @@ void mpu_configure_region(uintptr_t base, size_t size,
429
526
ARM_ISB ();
430
527
}
431
528
529
+ /****************************************************************************
530
+ * Name: mpu_configure_region
531
+ *
532
+ * Description:
533
+ * Configure a region for privileged, strongly ordered memory
534
+ *
535
+ * Input Parameters:
536
+ * base - Base address of the region.
537
+ * size - Size of the region.
538
+ * flags - Flags to configure the region.
539
+ *
540
+ * Returned Value:
541
+ * The region number allocated for the configured region.
542
+ *
543
+ ****************************************************************************/
544
+
545
+ unsigned int mpu_configure_region (uintptr_t base , size_t size ,
546
+ uint32_t flags )
547
+ {
548
+ unsigned int region = mpu_allocregion ();
549
+ mpu_modify_region (region , base , size , flags );
550
+ return region ;
551
+ }
552
+
553
+ /****************************************************************************
554
+ * Name: mpu_initialize
555
+ *
556
+ * Description:
557
+ * Configure a region for privileged, strongly ordered memory
558
+ *
559
+ * Input Parameters:
560
+ * table - MPU initialization table.
561
+ * hfnmiena - A boolean indicating whether the MPU should enable the
562
+ * HFNMIENA bit.
563
+ * privdefena - A boolean indicating whether the MPU should enable the
564
+ * PRIVDEFENA bit.
565
+ *
566
+ * Returned Value:
567
+ * NULL.
568
+ *
569
+ ****************************************************************************/
570
+
571
+ void mpu_initialize (const struct mpu_region_s * table , bool hfnmiena ,
572
+ bool privdefena )
573
+ {
574
+ const struct mpu_region_s * conf ;
575
+ int index ;
576
+
577
+ mpu_control (false, false, false);
578
+ for (index = 0 ; index < nitems (table ); index ++ )
579
+ {
580
+ conf = & table [index ];
581
+ mpu_configure_region (conf -> base , conf -> size , conf -> flags );
582
+ }
583
+
584
+ mpu_control (true, hfnmiena , privdefena );
585
+ }
586
+
587
+ /****************************************************************************
588
+ * Name: mpu_dump_region
589
+ *
590
+ * Description:
591
+ * Dump the region that has been used.
592
+ *
593
+ * Input Parameters:
594
+ * None.
595
+ *
596
+ * Returned Value:
597
+ * None.
598
+ *
599
+ ****************************************************************************/
600
+
601
+ void mpu_dump_region (void )
602
+ {
603
+ int i ;
604
+ int count = 0 ;
605
+ uint32_t rasr ;
606
+ uint32_t rbar ;
607
+ uint32_t ctrl ;
608
+
609
+ /* Get free region */
610
+
611
+ ctrl = getreg32 (MPU_CTRL );
612
+ _info ("MPU-CTRL Enable:%" PRIu32 ", HFNMIENA:%" PRIu32 ","
613
+ "PRIVDEFENA:%" PRIu32 "\n" , ctrl & MPU_CTRL_ENABLE ,
614
+ ctrl & MPU_CTRL_HFNMIENA , ctrl & MPU_CTRL_PRIVDEFENA );
615
+ for (i = 0 ; i < CONFIG_ARM_MPU_NREGIONS ; i ++ )
616
+ {
617
+ putreg32 (i , MPU_RNR );
618
+ rasr = getreg32 (MPU_RASR );
619
+ rbar = getreg32 (MPU_RBAR );
620
+ _info ("MPU-%d, alignedbase=0%08X l2size=%" PRIu32 " SRD=%X"
621
+ "AP=%X XN=%u\n" , i , rbar & MPU_RBAR_ADDR_MASK ,
622
+ rasr & MPU_RASR_SIZE_MASK , rasr & MPU_RASR_SRD_MASK ,
623
+ rasr & MPU_RASR_AP_MASK , rasr & MPU_RASR_XN );
624
+ if (rasr & MPU_RASR_ENABLE )
625
+ {
626
+ count ++ ;
627
+ }
628
+ }
629
+
630
+ _info ("Total Use Region:%d, Remaining Available:%d\n" , count ,
631
+ CONFIG_ARM_MPU_NREGIONS - count );
632
+ }
633
+
432
634
/****************************************************************************
433
635
* Name: mpu_reset
434
636
*
435
637
* Description:
436
638
* Conditional public interface that resets the MPU to disabled during
437
639
* MPU initialization.
438
640
*
641
+ * Input Parameters:
642
+ * None.
643
+ *
644
+ * Returned Value:
645
+ * None.
646
+ *
439
647
****************************************************************************/
440
648
#if defined(CONFIG_ARM_MPU_RESET )
441
649
void mpu_reset ()
@@ -451,6 +659,12 @@ void mpu_reset()
451
659
* Conditional public interface that resets the MPU to disabled immediately
452
660
* after reset.
453
661
*
662
+ * Input Parameters:
663
+ * None.
664
+ *
665
+ * Returned Value:
666
+ * None.
667
+ *
454
668
****************************************************************************/
455
669
#if defined(CONFIG_ARM_MPU_EARLY_RESET )
456
670
void mpu_early_reset ()
0 commit comments