How to access peripherals device when enter user/unprivileged mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to access peripherals device when enter user/unprivileged mode

1,140 Views
liu_vince
Contributor I

Hi,

I have struggled for access the peripherals device under user/unprivileged mode for days.

Env: 

   RT1052

   IAR 8.3

   FreeRTOS 10.1.1

When I switch the task (FreeRTOS's) to unprivileged mode(CONTROL.nPRIV=1), access/read the the uart/i2c will cause a hardfault and the CFSR shows it's a bus fault:

CFSR = 00008200
Bus fault: Precise Data Access (address in BFAR)
Bus fault: BFAR Has Valid Contents

BFAR= 40184000 (uart base address)

The same code could run normally under privileged mode(CONTROL.nPRIV=0).

I have already configure 0x40000000 ~ 0x5FFFFFFF could be accessed under unprivileged mode via MPU. ( If not will generate a MemManage fault, that's correct according to ARM design document)

I also try to modify CSU_CSLx register(Central Security Unit) during the code running, but no any improvement.

But when I modify those initial configures bits may cause the code get same fault even under privileged mode. That's also make me confusion.

Would you please give me a hand?

Thank you!

0 Kudos
5 Replies

975 Views
liu_vince
Contributor I

Hi Sabina

Thanks for your reply!

I used FreeRTOS MPU function to create two tasks as:

xTaskCreate( priApp, "priApp", ( STACKSIZE ), 0, (configMAX_PRIORITIES - 1)| portPRIVILEGE_BIT, & xPriHandle );
xTaskCreate( unpriApp, "unpriApp", ( STACKSIZE ), 0, (configMAX_PRIORITIES - 1) , & xUnPriHandle );

static void priApp(void * unused) {
for(;;) {
static int number = 0;
printf("\r\nI'm a privileged app! %d \r\n",number++);
CTask::Sleep(3000); //running normally
}
}


static void unpriApp(void * unused) {
for(;;) {
CTask::Sleep(12000);
printf("\r\nI'm a user app!\r\n");  //will crash here!
}
}

the 0x40000000 ~ 0x5F000000 have be configured could be accessed via MPU in port.c (FreeRTOS):

/* By default allow everything to access the general peripherals. The
system peripherals and registers are protected. */
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
( portMPU_REGION_VALID ) |
( portGENERAL_PERIPHERALS_REGION );

portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
( portMPU_REGION_ENABLE );

BUT when the unprivileged task" unpriApp" run to "printf" will cause a bus fault.

CFSR = 00008200
Bus fault: Precise Data Access (address in BFAR)
Bus fault: BFAR Has Valid Contents
HFSR = 40000000
DFSR = 00000000
MMFAR= 40184010
BFAR= 40184010  (the address of base->BAUD )
AFSR = 00000000
SHCSR= 00010000

hard_fault_handler_c(unsigned int * hardfault_args = 0x80334118 (ucHeap + 213272))
<Exception frame>
LPUART_EnableInterrupts(LPUART_Type * base = 0x40184000, uint32_t mask = 4194304)
UartPutChar(class UartIO * this = 0x80606480, uint8_t outChar = '\r' (0x0D))
PutChar(class UartIO * this = 0x80606480, uint8_t outChar = '\n' (0x0A))
PutString(class CConsole * this = 0x806067D8, char const * pString = 0x80207862 "I'm a user app!\r\n")
ConsolePutString(char const * pString = 0x80207860 "\r\nI'm a user app!\r\n")
vprintf(char const * format = 0x80027F48 "\r\nI'm a user app!\r\n", va_list vlist = <struct>)
printf(char const * format = 0x80027F48 "\r\nI'm a user app!\r\n")
unpriApp(void * unused = 0x00000000)
[__RAM_VECTOR_TABLE_SIZE + 0]

IAR shows the it crashed at:

base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));

void LPUART_EnableInterrupts(LPUART_Type *base, uint32_t mask)
{
/*--------------- <<<<<<<< WHIS - CRITICAL SECTION START >>>>>>>> --------------*/
{
unsigned portBASE_TYPE uxSavedBasePri = portSET_INTERRUPT_MASK_FROM_ISR(); /* <<<<<<<< WHIS >>>>>>>> */
base->BAUD |= ((mask << 8) & (LPUART_BAUD_LBKDIE_MASK | LPUART_BAUD_RXEDGIE_MASK));
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
base->FIFO = (base->FIFO & ~(LPUART_FIFO_TXOF_MASK | LPUART_FIFO_RXUF_MASK))
| ((mask << 8) & (LPUART_FIFO_TXOFE_MASK | LPUART_FIFO_RXUFE_MASK));
#endif
mask &= 0xFFFFFF00U;
base->CTRL |= mask;

portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedBasePri); /* <<<<<<<< WHIS >>>>>>>> */
}
/*---------------- <<<<<<<< WHIS - CRITICAL SECTION END >>>>>>>> ---------------*/
}

The privileged/unprivileged switch will be done in the task switch, by the pendSV handler, implemented by the FreeRTOS. 

Is there something else except MPU protecting the peripheral devices inside the RT105x?

Thank you.

0 Kudos

976 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Vince,

Hope you are doing well.

Could you please specify how you are unprivileged mode(CONTROL.nPRIV=1), so I can check it.

Here are the recommendations from ARM's documentation on changing the control privileged mode. 

ARM Information Center 

Best Regards,

Sabina

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

----------------------------------------------------------------------------------------------------------------------- 

0 Kudos

976 Views
liu_vince
Contributor I

Hi Sabina,

I'm not sure I provided enough information... Did you find something interesting about it?

Thank you! 

0 Kudos

976 Views
Sabina_Bruce
NXP Employee
NXP Employee

Hello Vince,

Hope you are doing well.

I find that it may be possible that the Central Security Unit may have to do with the peripheral access. The CSU can determine the privilege level for the peripherals as you are trying to do. The details on the CSU are located in the security reference manual

In addition, if possible could you share a simple example project with this issue. It doesn't have to be your full application just enough for me to reproduce this from my end. You can attach a zip folder on this thread. 

Best Regards,

Sabina

-----------------------------------------------------------------------------------------------------------------------

Note: If this post answers your question, please click the Correct Answer button. Thank you!

----------------------------------------------------------------------------------------------------------------------- 

0 Kudos

976 Views
liu_vince
Contributor I

Hi Sabina,

Thanks for helping!

I tried to modify CSU register(during the code) as I mentioned before.But seems it still not work normally. Is it need some special operation?

I create a smallest test code to trigger it and attach it. Would you please have look? this test code will run normal for about 3000 "tickless" time and then trigger the hardfault (via access the uart address in unprivileged mode).

I assume that you already have FreeRTOS MPU wrap implement for RT1050.

Thank you!

0 Kudos