PMP address modes on FreeRTOS

I am using the FreeRTOS example from the Freedom E SDK, and the PMP address setting really confused me. Here is a section from the pmp_blinky example.

// authorize access to data and bss
		// 		Low address 
        xTaskRXDefinition.xRegions[0].ulLengthInBytes = 4;
        xTaskRXDefinition.xRegions[0].ulParameters = ((portPMP_REGION_READ_WRITE) |
                                                    (portPMP_REGION_ADDR_MATCH_NA4));
        addr_modifier ( xPmpInfo.granularity,
                        ( size_t ) __unprivileged_data_section_start__,
                        (size_t *) &xTaskRXDefinition.xRegions[0].pvBaseAddress);

		// 		High address 
        xTaskRXDefinition.xRegions[1].ulLengthInBytes = 4;
        xTaskRXDefinition.xRegions[1].ulParameters = ((portPMP_REGION_READ_WRITE) |
                                                    (portPMP_REGION_ADDR_MATCH_TOR));

        addr_modifier ( xPmpInfo.granularity,
                        ( size_t ) __unprivileged_data_section_end__,
                        (size_t *) &xTaskRXDefinition.xRegions[1].pvBaseAddress);

#ifdef METAL_SIFIVE_UART0
    // allow access to UART peripheral
        xTaskRXDefinition.xRegions[2].ulLengthInBytes = METAL_SIFIVE_UART0_0_SIZE;
        xTaskRXDefinition.xRegions[2].ulParameters = ((portPMP_REGION_READ_WRITE) |
                                                     (portPMP_REGION_ADDR_MATCH_NAPOT));

        napot_addr_modifier (	xPmpInfo.granularity,
                                (size_t) METAL_SIFIVE_UART0_0_BASE_ADDRESS,
                                (size_t *) &xTaskRXDefinition.xRegions[2].pvBaseAddress,
                                xTaskRXDefinition.xRegions[2].ulLengthInBytes);
#endif /* METAL_SIFIVE_UART0 */

// allocate stack (It will take 2 PMP Slot - So it is not needed to put align the StackBuffer)
        xTaskRXDefinition.puxStackBuffer = ( StackType_t * ) pvPortMalloc( xTaskRXDefinition.usStackDepth * sizeof( StackType_t ) );

  1. What is Top-of-Range address mode mean? Does it mean memory access will be configured from xRegion[0] to xRegion[1]?

  2. The allocation said it takes two PMP slot and does not need to be aligned, what does that mean? My understanding is, the allocation will first generate two PMP entries for this task (using low and high addresses shown above), and allocated the memory in between them, so it is naturally aligned right?

  3. NAPOT and NA4 alignment difference. My thought:

    • NA4 is for the low-high-range address operation, it aligns address to 4 bytes only, since PMP has a granularity of 4 bytes.
    • NAPOT is for most cases, it aligns address to block size, which must be the power of 2(? No sure why this is needed) and (of course) 4 bytes.

Can someone provide any ideas on my thought?

Ok I think I got it, the UART address range is NAPOT compatible, so we can use only one entry for that. If it is not NAPOT compatible (meaning starting address is not aligned to size, or size is not a power of 2), it has to be registered in TOR mode.

Uh, I hope the FreeRTOS port can provide a more similar way (like configuring MPU in FreeRTOS) for PMP. :upside_down_face: Why it has to be so different from each other.

Hi Xiahua.
You are right the PMP permit support NAPOT or not NAPOT address range. The purpose of this example is to demonstrate these 2 methods of protection. we believe it could be useful to reduce constraint on the stack alignment/size (even if it will request to use two pmp entries instead of one). If you prefer to use it like MPU from ARM, it still possible :wink:

1 Like