What is the minimum number of MPU regions that your boot code need? It is currently using 8 but is that the minimum required?
Something like this - https://www.ti.com/product/TMS570LC4357.
What is the minimum number of MPU regions that your boot code need? It is currently using 8 but is that the minimum required?
Something like this - https://www.ti.com/product/TMS570LC4357.
I will try to check the minimum number of MPU regions the boot code need.
It seems FreeRTOS v11.1 CR5 port only support 12 or 16 MPU regions, is it right?
The hardware support total 16 MPU regions, maybe i can provide 12 to FreeRTOS and 4 to boot code.
The document can be downloaded from below url:
https://documentation-service.arm.com/static/5f04288cdbdee951c1cd8969?token=
I have change MPU regions which were need by boot code to 4(12-15), and
#define configTOTAL_MPU_REGIONS 12U
The latest boot.S has been uploaded to
After above update, below line can pass.
CPS #SVC_MODE
But the code stuck in below line now:
portRESTORE_CONTEXT
The fucntion’s code is:
/*
* void vPortStartFirstTask( void );
*/
.align 4
.global vPortStartFirstTask
.type vPortStartFirstTask, %function
vPortStartFirstTask:
/* This function is called from System Mode to start the FreeRTOS-Kernel.
* As described in the portRESTORE_CONTEXT macro, portRESTORE_CONTEXT cannot
* be called from the System mode. We, therefore, switch to the Supervisor
* mode before calling portRESTORE_CONTEXT. */
CPS #SVC_MODE
portRESTORE_CONTEXT
appreciate for your advice.
Can you look into the disassembly and find the exact instruction? If you would like to have a debug session to debug this together, please drop me a DM.
/* Restore the context of a FreeRTOS Task. */
.macro portRESTORE_CONTEXT
/* Load the pointer to the current task's Task Control Block (TCB). */
LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */
LDR LR, [LR] /* LR = pxCurrentTCB. */
ADD R1, LR, #0x4 /* R1 now points to the xMPUSettings in TCB. */
LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to restore the task context from. */
/* When creating a loop label in a macro it has to be a numeric label.
* for( R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portNUM_CONFIGURABLE_REGIONS ; R5++ ) */
MOV R5, #portFIRST_CONFIGURABLE_REGION
123:
LDMIA R1!, { R2-R4 } /* R2 = ulRegionSize, R3 = ulRegionAttribute, R4 = ulRegionBaseAddress. */
MCR p15, #0, R5, c6, c2, #0 /* MPU Region Number Register. */
MCR p15, #0, R4, c6, c1, #0 /* MPU Region Base Address Register. */
MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */
MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */
ADD R5, R5, #1
CMP R5, #portNUM_CONFIGURABLE_REGIONS
BLE 123b
LDR R1, =ulCriticalNesting /* R1 = &( ulCriticalNesting ). */
LDM LR!, { R2 } /* R2 = Stored ulCriticalNesting. */
STR R2, [R1] /* Restore ulCriticalNesting. */
#if ( portENABLE_FPU == 1 )
LDM LR!, { R1 } /* R1 = Stored FPSCR. */
VMSR FPSCR, R1 /* Restore FPSCR. */
VLDM LR!, { D0-D15 } /* Restore D0-D15. */
#endif /* portENABLE_FPU*/
/* LDM (User registers) - In a PL1 mode other than System mode, LDM (User
* registers) loads multiple User mode registers from consecutive memory
* locations using an address from a base register. The registers loaded
* cannot include the PC. The processor reads the base register value
* normally, using the current mode to determine the correct Banked version
* of the register. This instruction cannot writeback to the base register.
*
* The following can be derived from the above description:
* - The macro portRESTORE_CONTEXT MUST be called from a PL1 mode other than
* the System mode.
* - Base register LR of the current mode will be used which contains the
* location to restore the context from.
* - It will restore R0-R14 of User mode i.e. SP(R13) and LR(R14) of User
* mode will be restored.
*/
LDM LR, { R0-R14 }^
ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */
RFE LR /* Restore PC and CPSR from the context. */
.endm
RFE LR
The above line stuck. @aggarg
What is the value of SP and LR before executing RFE LR? What are the 2 words stored at the address in register LR?
LDR r12, =0xB7000000
LDR R13, [LR]
STR r13, [r12]
LDR R13, [LR, #4]
STR r13, [r12, #4]
RFE LR /* Restore PC and CPSR from the context. */
Sf:/$ dump 0xB7000000 0x10
ADDR 0xb7000000: 0x0510769c
ADDR 0xb7000004: 0x0000001f
ADDR 0xb7000008: 0x00000000
ADDR 0xb700000c: 0x00000000
ADDR 0xb7000010: 0x00000000
ADDR 0xb7000014: 0x00000000
ADDR 0xb7000018: 0x00000000
ADDR 0xb700001c: 0x00000000
ADDR 0xb7000020: 0x00000000
ADDR 0xb7000024: 0x00000000
ADDR 0xb7000028: 0x00000000
ADDR 0xb700002c: 0x00000000
ADDR 0xb7000030: 0x00000000
ADDR 0xb7000034: 0x00000000
ADDR 0xb7000038: 0x00000000
ADDR 0xb700003c: 0x00000000
Please check, thank you .
This code looks different than what you shared in the previous post. Where did you take it?
What is address 0xB7000000? Is it the value contained in LR register?
0xB7000000 is just a address used to debug and dump the LR value.
The real 2 words of LR are:
0x0510769c and 0x0000001f .
LDR r12, =0xB7000000
LDR R13, [LR]
STR r13, [r12]
LDR R13, [LR, #4]
STR r13, [r12, #4]
above code snippets do that save LR value to 0xB7000000.
The whole code:
/* Restore the context of a FreeRTOS Task. */
.macro portRESTORE_CONTEXT
/* Load the pointer to the current task's Task Control Block (TCB). */
LDR LR, =pxCurrentTCB /* LR = &( pxCurrentTCB ). */
LDR LR, [LR] /* LR = pxCurrentTCB. */
ADD R1, LR, #0x4 /* R1 now points to the xMPUSettings in TCB. */
LDR LR, [LR] /* LR = pxTopOfStack i.e. the address where to restore the task context from. */
/* When creating a loop label in a macro it has to be a numeric label.
* for( R5 = portFIRST_CONFIGURABLE_REGION ; R5 <= portNUM_CONFIGURABLE_REGIONS ; R5++ ) */
MOV R5, #portFIRST_CONFIGURABLE_REGION
123:
LDMIA R1!, { R2-R4 } /* R2 = ulRegionSize, R3 = ulRegionAttribute, R4 = ulRegionBaseAddress. */
MCR p15, #0, R5, c6, c2, #0 /* MPU Region Number Register. */
MCR p15, #0, R4, c6, c1, #0 /* MPU Region Base Address Register. */
MCR p15, #0, R3, c6, c1, #4 /* MPU Region Access Control Register. */
MCR p15, #0, R2, c6, c1, #2 /* MPU Region Size and Enable Register. */
ADD R5, R5, #1
CMP R5, #portNUM_CONFIGURABLE_REGIONS
BLE 123b
LDR R1, =ulCriticalNesting /* R1 = &( ulCriticalNesting ). */
LDM LR!, { R2 } /* R2 = Stored ulCriticalNesting. */
STR R2, [R1] /* Restore ulCriticalNesting. */
#if ( portENABLE_FPU == 1 )
LDM LR!, { R1 } /* R1 = Stored FPSCR. */
VMSR FPSCR, R1 /* Restore FPSCR. */
VLDM LR!, { D0-D15 } /* Restore D0-D15. */
#endif /* portENABLE_FPU*/
/* LDM (User registers) - In a PL1 mode other than System mode, LDM (User
* registers) loads multiple User mode registers from consecutive memory
* locations using an address from a base register. The registers loaded
* cannot include the PC. The processor reads the base register value
* normally, using the current mode to determine the correct Banked version
* of the register. This instruction cannot writeback to the base register.
*
* The following can be derived from the above description:
* - The macro portRESTORE_CONTEXT MUST be called from a PL1 mode other than
* the System mode.
* - Base register LR of the current mode will be used which contains the
* location to restore the context from.
* - It will restore R0-R14 of User mode i.e. SP(R13) and LR(R14) of User
* mode will be restored.
*/
LDM LR, { R0-R14 }^
ADD LR, LR, #60 /* R0-R14 - Total 155 register, each 4 byte wide. */
LDR r12, =0xB7000000
LDR R13, [LR]
STR r13, [r12]
LDR R13, [LR, #4]
STR r13, [r12, #4]
RFE LR /* Restore PC and CPSR from the context. */
.endm
Thanks.
This indicates that we are trying to start a privileged task.
Does this look like a valid code section address? Can you examine the code at that address and see if it looks reasonable?
In the code you added, you are clobbering R13 which is SP. Use some other general purpose register and check the SP value also to see if looks reasonable.
update code as below:
LDR r12, =0xB7000000
LDR r11, [LR]
STR r11, [r12]
LDR r11, [LR, #4]
STR r11, [r12, #4]
RFE LR /* Restore PC and CPSR from the context. */
dump result:
Sf:/$ dump 0xB7000000 0x10
ADDR 0xb7000000: 0x0510769c
ADDR 0xb7000004: 0x0000001f
All that seems reasonable. The RFE should take the control to timer task. Not sure why that is not happening. Just for testing, can you update your boot code to use MPU regions 8-16 so that you do not need to comment out any MPU region configuration in the boot code? Leave configTOTAL_MPU_REGIONS as 12.
I think the region ID should be from 8-15, right?
I have done the testing follow your advice.
But it’s failed.
The code stuck when call vPortStartFirstTask function, It’s not even executed inside this function.
Yes, you are right.
I am out of ideas here. We can have a debug session together and try to debug. I’d also suggest to reach out to your hardware vendor.
thank you.
Could you tell me how to setup a debug session, and which software need to install for it?
Send me a DM with your email and I will setup one.
Some update:
The function xTaskCreateRestricted which used to create task stuck,
further function pvPortMalloc called in prvCreateRestrictedTask stuck.
We use in heap_4.c.
We had a debug session and we concluded that the OP’s initial assertion that the code is stuck in RFE LR is not correct. The OP incorrectly concluded that from the observation that vPortStartFirstTask was not returning. In reality, this function is not meant to return and the control successfully reaches the first task (timer task in this case).
Please try to figure out where in pvPortMalloc is it stuck.
Both xTaskCreateRestricted and pvPortMalloc have been called successed.
But vTaskFunction can not be scheduled:
void vTaskFunction(void* p) {
int* pp = 0xb7000001c;
int a = 0x1111;
*pp = a;
for (;;)
{
*pp = a++;
vTaskDelay(pdMS_TO_TICKS(1000));
}
}