Hello,
We're currently facing a weird problem with our project and FreeRTOS. I've asked in the FreeRTOS forum (see FreeRTOS Forum post), but within the investigation it seems to me that the problem might be not directly linked with FreeRTOS itself. Please be aware that I'm not an expert in assembly language.
The original problem manifests itself in the program hanging in one of the RTOS asserts on system power up. After some forward and backward (see other thread), my conclusion is that, at boot, when the RTOS uses the sleep function for the first time, one of the CPU registers is cleared without any obvious reason. This leads to the assert further down the chain. This is the sleep function: (sleep function source code). This is called in the idle task: idle task source. This is the assert: Tick plausability. The assert fails because the value of xTickCount is invalid. I've analysed the assembly to the point that at the beginning of the function, CPU reg R7 is set as pointer to xTickCount. This register is then de-referenced later again, to get the tick for the assert. At this point, however, the register contains the value "0", leading to another value being loaded. I've narrowed it down to a few lines after the call to "wfi".
volatile uint32_t test5257; volatile uint32_t test5258; ... vPortSuppressTicksAndSleep() ... __asm volatile("mov %0, r7" : "=r" (test5257)); if( xModifiableIdleTime > 0 ) { __asm volatile ( "dsb" ::: "memory" ); __asm volatile ( "wfi" ); __asm volatile ( "isb" ); } configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); //don't enable interrupt processing here, just to be sure... //__asm volatile ( "cpsie i" ::: "memory" ); <----------------- __asm volatile ("nop" ::: "memory"); __asm volatile ( "dsb" ); __asm volatile ( "isb" ); // <--------------------------------- __asm volatile("mov %0, r7" : "=r" (test5258)); ...
when I pause the target with the debugger and read the values of the variables, "test5257" contains a pointer to xTickCount and "test5258" contains "0". When i patch the second "isb" directly in the binary to a 4 byte "nop", the pointer remains valid and the assertion is gone. I can't see any reason why the value of the register should change as a result of the "isb" instruction.
I would appreciate any help on understanding what causes this behaviour. As adding/removing code sometimes "fixes" the error, I have no idea how I can check if a change actually fixed the underlying problem...
regards, Martin
Details for our system:
This is the full assembly for the function above:
prvIdleTask.lto_priv.54: 08000f78: push {r7, lr} 6152 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); 08000f7a: ldr r6, [pc, #576] ; (0x80011bc <prvIdleTask.lto_priv.54+580>) 5881 taskYIELD(); 08000f7c: ldr r5, [pc, #576] ; (0x80011c0 <prvIdleTask.lto_priv.54+584>) 6142 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) 08000f7e: ldr r7, [pc, #580] ; (0x80011c4 <prvIdleTask.lto_priv.54+588>) 6154 --uxCurrentNumberOfTasks; 08000f80: ldr.w r8, [pc, #616] ; 0x80011ec <prvIdleTask.lto_priv.54+628> 6142 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) 08000f84: ldr r3, [r7, #0] 08000f86: cbnz r3, 0x8000fd6 <prvIdleTask.lto_priv.54+94> 5879 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) configNUMBER_OF_CORES ) 08000f88: ldr r3, [pc, #572] ; (0x80011c8 <prvIdleTask.lto_priv.54+592>) 08000f8a: ldr r3, [r3, #0] 08000f8c: cmp r3, #1 08000f8e: bls.n 0x8000f9e <prvIdleTask.lto_priv.54+38> 5881 taskYIELD(); 08000f90: mov.w r3, #268435456 ; 0x10000000 08000f94: str r3, [r5, #0] 08000f96: dsb sy 08000f9a: isb sy 68 wdt_trigger(wdt_idle_reference); 08000f9e: ldr r3, [pc, #556] ; (0x80011cc <prvIdleTask.lto_priv.54+596>) 08000fa0: ldrb r0, [r3, #0] 08000fa2: bl 0x8000f68 <wdt_trigger> 202 wdt_states[reference] = WDT_STATE_ALIVE; 08000fa6: bl 0x80002c8 <prvGetExpectedIdleTime> 5912 if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) 08000faa: cmp r0, #1 08000fac: bls.n 0x8000f7e <prvIdleTask.lto_priv.54+6> 5920 test3261 = xTickCount; 08000fae: ldr r7, [pc, #544] ; (0x80011d0 <prvIdleTask.lto_priv.54+600>) 5914 vTaskSuspendAll(); 08000fb0: bl 0x8000bd4 <vTaskSuspendAll> 5920 test3261 = xTickCount; 08000fb4: ldr r3, [pc, #540] ; (0x80011d4 <prvIdleTask.lto_priv.54+604>) 08000fb6: ldr r2, [r7, #0] 5923 configASSERT( xNextTaskUnblockTime >= test3261 ); 08000fb8: ldr r1, [pc, #540] ; (0x80011d8 <prvIdleTask.lto_priv.54+608>) 5920 test3261 = xTickCount; 08000fba: str r2, [r3, #0] 08000fbc: ldr r2, [r1, #0] 08000fbe: ldr r3, [r3, #0] 08000fc0: cmp r2, r3 08000fc2: bcs.n 0x800100e <prvIdleTask.lto_priv.54+150> 217 __asm volatile 08000fc4: mov.w r3, #80 ; 0x50 08000fc8: msr BASEPRI, r3 08000fcc: isb sy 08000fd0: dsb sy 08000fd4: b.n 0x8000fd4 <prvIdleTask.lto_priv.54+92> 6146 taskENTER_CRITICAL(); 08000fd6: bl 0x80013e8 <vPortEnterCritical> 6152 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); 08000fda: ldr r3, [r6, #12] 08000fdc: ldr r4, [r3, #12] 6153 ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); 08000fde: adds r0, r4, #4 08000fe0: bl 0x80023ac <uxListRemove> 6154 --uxCurrentNumberOfTasks; 08000fe4: ldr.w r3, [r8] 08000fe8: subs r3, #1 08000fea: str.w r3, [r8] 6158 --uxDeletedTasksWaitingCleanUp; 08000fee: ldr r3, [r7, #0] 08000ff0: subs r3, #1 08000ff2: str r3, [r7, #0] 6163 taskEXIT_CRITICAL(); 08000ff4: bl 0x80013c0 <vPortExitCritical> 6506 configDEINIT_TLS_BLOCK( pxTCB->xTLSBlock ); 08000ff8: add.w r0, r4, #72 ; 0x48 08000ffc: bl 0x8002760 <_reclaim_reent> 6514 vPortFreeStack( pxTCB->pxStack ); 08001000: ldr r0, [r4, #48] ; 0x30 08001002: bl 0x8001338 <vPortFree> 6515 vPortFree( pxTCB ); 08001006: mov r0, r4 08001008: bl 0x8001338 <vPortFree> 0800100c: b.n 0x8000f84 <prvIdleTask.lto_priv.54+12> 5927 xExpectedIdleTime = prvGetExpectedIdleTime(); 0800100e: bl 0x80002c8 <prvGetExpectedIdleTime> 5934 if( xExpectedIdleTime >= ( TickType_t ) configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) 08001012: cmp r0, #1 08001014: bls.w 0x80011b6 <prvIdleTask.lto_priv.54+574> ......... ... 08001019: ldr r3, [pc, #448] ; (0x80011dc <prvIdleTask.lto_priv.54+612>) 0800101b: ldr r3, [r3, #0] 0800101d: cpsid i 0800101f: dsb sy ......... isb sy 5986 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0U ) 08001026: ldr r2, [pc, #440] ; (0x80011e0 <prvIdleTask.lto_priv.54+616>) 08001028: ldr r2, [r2, #0] 0800102a: cmp r2, #0 0800102c: bne.w 0x80011b4 <prvIdleTask.lto_priv.54+572> 5991 else if( xYieldPendings[ portGET_CORE_ID() ] != pdFALSE ) 08001030: ldr r2, [pc, #432] ; (0x80011e4 <prvIdleTask.lto_priv.54+620>) 08001032: ldr r2, [r2, #0] 08001034: cmp r2, #0 08001036: bne.w 0x80011b4 <prvIdleTask.lto_priv.54+572> 5996 else if( xPendedTicks != 0U ) 0800103a: ldr.w r8, [pc, #464] ; 0x800120c <prvIdleTask.lto_priv.54+660> 0800103e: ldr.w r2, [r8] 08001042: cmp r2, #0 08001044: bne.w 0x80011b4 <prvIdleTask.lto_priv.54+572> 6004 else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) 08001048: ldr r2, [pc, #412] ; (0x80011e8 <prvIdleTask.lto_priv.54+624>) 0800104a: ldr.w lr, [pc, #452] ; 0x8001210 <prvIdleTask.lto_priv.54+664> 0800104e: ldr r2, [r2, #0] 08001050: ldr r2, [pc, #408] ; (0x80011ec <prvIdleTask.lto_priv.54+628>) 08001052: ldr r2, [r2, #0] 629 portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); 08001054: ldr r2, [pc, #408] ; (0x80011f0 <prvIdleTask.lto_priv.54+632>) 08001056: movs r4, #6 08001058: str r4, [r2, #0] 636 ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG; 0800105a: adds r2, #8 0800105c: ldr r2, [r2, #0] 638 if( ulSysTickDecrementsLeft == 0 ) 0800105e: cbnz r2, 0x8001064 <prvIdleTask.lto_priv.54+236> 640 ulSysTickDecrementsLeft = ulTimerCountsForOneTick; 08001060: ldr.w r2, [lr] 08001064: cmp r0, r3 08001066: it cs 08001068: movcs r0, r3 649 ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); 0800106a: ldr.w r3, [lr] 0800106e: subs r4, r0, #1 08001070: mla r12, r3, r4, r2 651 if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 ) 08001074: ldr r3, [r5, #0] 08001076: lsls r3, r3, #5 653 portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT; 08001078: itttt mi 0800107a: movmi.w r3, #33554432 ; 0x2000000 0800107e: strmi r3, [r5, #0] 654 ulReloadValue -= ulTimerCountsForOneTick; 08001080: ldrmi.w r2, [lr] 08001084: submi.w r12, r12, r2 657 if( ulReloadValue > ulStoppedTimerCompensation ) 08001088: ldr r2, [pc, #360] ; (0x80011f4 <prvIdleTask.lto_priv.54+636>) 0800108a: ldr r3, [r2, #0] 0800108c: cmp r3, r12 659 ulReloadValue -= ulStoppedTimerCompensation; 0800108e: it cc 08001090: subcc.w r12, r12, r3 663 portNVIC_SYSTICK_LOAD_REG = ulReloadValue; 08001094: ldr r3, [pc, #352] ; (0x80011f8 <prvIdleTask.lto_priv.54+640>) 667 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; 08001096: mov.w r9, #0 663 portNVIC_SYSTICK_LOAD_REG = ulReloadValue; 0800109a: str.w r12, [r3] 667 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; 0800109e: str.w r9, [r3, #4] 670 portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; 080010a2: ldr.w r9, [pc, #332] ; 0x80011f0 <prvIdleTask.lto_priv.54+632> 080010a6: ldr.w r3, [r9] 080010aa: orr.w r3, r3, #1 080010ae: str.w r3, [r9] 680 __asm volatile("mov %0, r7" : "=r" (test5257)); 080010b2: mov r3, r7 080010b4: ldr.w r9, [pc, #348] ; 0x8001214 <prvIdleTask.lto_priv.54+668> 080010b8: str.w r3, [r9] 681 if( xModifiableIdleTime > 0 ) 080010bc: cbz r0, 0x80010c8 <prvIdleTask.lto_priv.54+336> 683 __asm volatile ( "dsb" ::: "memory" ); 080010be: dsb sy 684 __asm volatile ( "wfi" ); 080010c2: wfi 685 __asm volatile ( "isb" ); 080010c4: isb sy 695 __asm volatile ("nop" ::: "memory"); 080010c8: nop 696 __asm volatile ( "dsb" ); ----------------> 080010ca: dsb sy 705 __asm volatile ( "isb" ); 080010ce: isb sy 715 __asm volatile("mov %0, r7" : "=r" (test5258)); <---------------- 080010d2: mov r3, r7 080010d4: ldr.w r9, [pc, #320] ; 0x8001218 <prvIdleTask.lto_priv.54+672> 080010d8: str.w r3, [r9] 722 __asm volatile ( "cpsid i" ::: "memory" ); 080010dc: cpsid i 723 __asm volatile ( "dsb" ); 080010de: dsb sy 724 __asm volatile ( "isb" ); 080010e2: isb sy 733 portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); 080010e6: ldr r3, [pc, #264] ; (0x80011f0 <prvIdleTask.lto_priv.54+632>) 080010e8: mov.w r9, #6 080010ec: str.w r9, [r3] 736 if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) 080010f0: ldr r3, [r3, #0] 080010f2: tst.w r3, #65536 ; 0x10000 080010f6: ldr r3, [pc, #260] ; (0x80011fc <prvIdleTask.lto_priv.54+644>) 080010f8: beq.n 0x8001152 <prvIdleTask.lto_priv.54+474> 743 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); 080010fa: ldr.w r0, [lr] 080010fe: ldr r3, [r3, #0] 749 if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) 08001100: ldr r2, [r2, #0] 743 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); 08001102: add r3, r0 08001104: subs r3, #1 08001106: sub.w r3, r3, r12 749 if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) 0800110a: cmp r3, r2 0800110c: bls.n 0x8001112 <prvIdleTask.lto_priv.54+410> 0800110e: cmp r0, r3 08001110: bcs.n 0x8001114 <prvIdleTask.lto_priv.54+412> 751 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); 08001112: subs r3, r0, #1 794 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; 08001114: ldr r2, [pc, #224] ; (0x80011f8 <prvIdleTask.lto_priv.54+640>) 08001116: str r3, [r2, #0] 804 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; 08001118: ldr r3, [pc, #224] ; (0x80011fc <prvIdleTask.lto_priv.54+644>) 0800111a: movs r2, #0 0800111c: str r2, [r3, #0] 805 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; 0800111e: movs r2, #7 08001120: str.w r2, [r3, #-8] 808 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; 08001124: ldr.w r3, [lr] 08001128: ldr r2, [pc, #204] ; (0x80011f8 <prvIdleTask.lto_priv.54+640>) 0800112a: subs r3, #1 0800112c: str r3, [r2, #0] 4583 xUpdatedTickCount = test3257 + test3258; 0800112e: ldr r3, [pc, #208] ; (0x8001200 <prvIdleTask.lto_priv.54+648>) 08001130: ldr r3, [r3, #0] 08001132: ldr r3, [pc, #208] ; (0x8001204 <prvIdleTask.lto_priv.54+652>) 08001134: ldr r3, [r3, #0] 4584 xUpdatedTickCount = xTickCount + xTicksToJump; 08001136: ldr r3, [r7, #0] 4588 configASSERT( xUpdatedTickCount <= xNextTaskUnblockTime ); 08001138: ldr r2, [r1, #0] 4584 xUpdatedTickCount = xTickCount + xTicksToJump; 0800113a: add r3, r4 4588 configASSERT( xUpdatedTickCount <= xNextTaskUnblockTime ); 0800113c: cmp r3, r2 0800113e: bls.n 0x8001168 <prvIdleTask.lto_priv.54+496> 08001140: mov.w r3, #80 ; 0x50 08001144: msr BASEPRI, r3 08001148: isb sy 0800114c: dsb sy 08001150: b.n 0x8001150 <prvIdleTask.lto_priv.54+472> 08001152: ldr r2, [r3, #0] 08001154: ldr.w r3, [lr] 08001158: muls r0, r3 0800115a: subs r0, r0, r2 0800115c: udiv r4, r0, r3 08001160: mla r3, r4, r3, r3 08001164: subs r3, r3, r0 08001166: b.n 0x8001114 <prvIdleTask.lto_priv.54+412> 08001168: ldr r2, [r1, #0] 0800116a: cmp r3, r2 0800116c: bne.n 0x80011ae <prvIdleTask.lto_priv.54+566> 0800116e: ldr r3, [pc, #152] ; (0x8001208 <prvIdleTask.lto_priv.54+656>) 08001170: ldr r3, [r3, #0] 08001172: cbnz r3, 0x8001186 <prvIdleTask.lto_priv.54+526> 08001174: mov.w r3, #80 ; 0x50 08001178: msr BASEPRI, r3 0800117c: isb sy 08001180: dsb sy 08001184: b.n 0x8001184 <prvIdleTask.lto_priv.54+524> 4596 configASSERT( xTicksToJump != ( TickType_t ) 0 ); 08001186: cbnz r4, 0x800119a <prvIdleTask.lto_priv.54+546> 08001188: mov.w r3, #80 ; 0x50 0800118c: msr BASEPRI, r3 08001190: isb sy 08001194: dsb sy 08001198: b.n 0x8001198 <prvIdleTask.lto_priv.54+544> 0800119a: bl 0x80013e8 <vPortEnterCritical> 4601 xPendedTicks++; 0800119e: ldr.w r3, [r8] 080011a2: adds r3, #1 080011a4: str.w r3, [r8] 4603 taskEXIT_CRITICAL(); 080011a8: bl 0x80013c0 <vPortExitCritical> 4604 xTicksToJump--; 080011ac: subs r4, #1 4614 xTickCount += xTicksToJump; 080011ae: ldr r3, [r7, #0] 080011b0: add r4, r3 080011b2: str r4, [r7, #0] 832 __asm volatile ( "cpsie i" ::: "memory" ); 080011b4: cpsie i 5945 ( void ) xTaskResumeAll(); 080011b6: bl 0x8000a90 <xTaskResumeAll> 080011ba: b.n 0x8000f7e <prvIdleTask.lto_priv.54+6> 080011bc: lsls r4, r1, #5 080011be: movs r0, #0 080011c0: stc 0, cr14, [r4, #-0] 080011c4: lsls r0, r0, #3 080011c6: movs r0, #0 080011c8: lsls r0, r7, #6 080011ca: movs r0, #0 080011cc: lsls r0, r7, #5 080011ce: movs r0, #0 080011d0: lsls r4, r2, #12 080011d2: movs r0, #0 080011d4: movs r4, r2 080011d6: movs r0, #0 080011d8: lsls r4, r2, #6 080011da: movs r0, #0 080011dc: lsls r0, r2, #6 080011de: movs r0, #0 080011e0: lsls r4, r4, #4 080011e2: movs r0, #0 080011e4: lsls r0, r3, #12 080011e6: movs r0, #0 080011e8: lsls r0, r7, #4 080011ea: movs r0, #0 080011ec: lsls r0, r6, #12 080011ee: movs r0, #0 080011f0: b.n 0x8001214 <prvIdleTask.lto_priv.54+668> 080011f2: b.n 0x80011f6 <prvIdleTask.lto_priv.54+638> 080011f4: lsls r0, r6, #5 080011f6: movs r0, #0 080011f8: b.n 0x8001224 <PendSV_Handler+4> 080011fa: b.n 0x80011fe <prvIdleTask.lto_priv.54+646> 080011fc: b.n 0x8001230 <PendSV_Handler+16> 080011fe: b.n 0x8001202 <prvIdleTask.lto_priv.54+650> 08001200: movs r4, r1 08001202: movs r0, #0 08001204: movs r0, r2 08001206: movs r0, #0 08001208: lsls r4, r0, #3 0800120a: movs r0, #0 0800120c: lsls r0, r4, #4 0800120e: movs r0, #0 08001210: lsls r4, r6, #5 08001212: movs r0, #0 08001214: movs r0, r3 08001216: movs r0, #0 08001218: movs r4, r3 0800121a: movs r0, #0 0800121c: movs r0, r0 0800121e: movs r0, r0